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

📄 geotrans.cpp

📁 用C++实现的数字图像处理各个算法源代码 我精心整理的 很难的啊 希望可以给大家带来帮助
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		break;
	case 24:
		nMovedBits = 3;
		break;
	case 32:
		nMovedBits = 4;
		break;
	}

	//针对图像每行进行操作
	for(y = 0; y < nNewHeight; y++)
	{
		//指向新图像第y行
		//注意此处宽度和高度是新图像的宽度和高度
		pNewTemp = pNewBits;
		pNewTemp += (nNewHeight - 1 - y) * nNewWidthBytes;
		//针对图像每列进行操作
		for(x = 0; x < nNewWidth; x++)
		{
			//计算该像素在源图像中的坐标
			int y0 = (long) (y / fYZoomRatio + 0.5);
			int x0 = (long) (x / fXZoomRatio + 0.5);

			//判断是否在源图范围内
			if( (x0 >= 0) && (x0 < nOldWidth) && 
				(y0 >= 0) && (y0 < nOldHeight))
			{
				//用双线性插值
				if(bBilinear)
				{
					unsigned char *pTemp = Interpolation (nOldWidth, nOldHeight, 
						(float)x0, (float)y0, 
						nOldWidthBytes, nMovedBits, pOldBits);
					//复制像素
					memcpy(pNewTemp, pTemp, nMovedBits);
					
					delete [] pTemp ;
				}
				else
				{				
					//指向源图像第y0行,第x0个像素
					//注意此处宽度和高度应该互换
					pOldTemp = pOldBits;
					pOldTemp += (nOldHeight - 1 - y0) * nOldWidthBytes;
					pOldTemp += x0 * nMovedBits;
					
					//复制像素
					memcpy(pNewTemp, pOldTemp, nMovedBits);
				}
			}
			pNewTemp += nMovedBits;

		}
		
	}

	//将内存解锁和将不再使用的内存释放
	::GlobalUnlock( m_pDibObject->GetDib() );
	::GlobalFree( m_pDibObject->GetDib() );
	::GlobalUnlock( hNewDib );
	//将新图像设置为当前图像
	m_pDibObject->SetDib( hNewDib );

	m_pDibObject->ProcessImageHeader();

	return TRUE;
}

////////////////////////////////////////////////////////////////////////
//BOOL Rotate()  
//----------------------------------------------------------------------
//基本功能:本函数对传入的CDibObject对象中的图像进行旋转操作。如果进行
//			此调整之前没有指定一个CDibObject对象指针,则必须在调整时加
//			以指定。
//----------------------------------------------------------------------
//参数说明:int iRotateAngle	- 旋转的角度(0-360度)
//			BOOL bBilinear		- TRUE为双线性插值,FALSE为最邻近插值
//			CDibObject *pDibObject, 默认为NULL
//----------------------------------------------------------------------
//返回:BOOL:成功返回TRUE,失败返回FALSE。
//----------------------------------------------------------------------
//注	意:该函数用来以图像中心为中心旋转图像,调用该函数会自动扩大图像
//			以显示所有的像素。函数中采用最邻近插值算法进行插值。
////////////////////////////////////////////////////////////////////////
BOOL CGeoTrans::Rotate(int nRotateAngle,
							BOOL bBilinear,
							CDibObject *pDibObject)
{
	if( pDibObject != NULL ) m_pDibObject = pDibObject;
	//无CDibObject对象, 返回FALSE
	if( m_pDibObject == NULL ) return( FALSE );

	//获得图像宽度和高度
	int nOldWidth = m_pDibObject->GetWidth();
	int nOldHeight = m_pDibObject->GetHeight();

	//旋转角度(弧度)
	float	fRotateAngle;
	
	//旋转角度的正弦和余弦值
	float	fSina, fCosa;
	
	//源图四个角的坐标(以图像中心为坐标系原点)
	float	fSrcX1, fSrcY1;
	float	fSrcX2, fSrcY2;
	float	fSrcX3, fSrcY3;
	float	fSrcX4, fSrcY4;
	
	//旋转后四个角的坐标(以图像中心为坐标系原点)
	float	fDstX1, fDstY1;
	float	fDstX2, fDstY2;
	float	fDstX3, fDstY3;
	float	fDstX4, fDstY4;
	
	//两个中间常量
	float	f1,f2;

	//将旋转角度从度转换到弧度
	fRotateAngle = (float) RADIAN(nRotateAngle);

	//计算旋转角度的正弦
	fSina = (float) sin((double)fRotateAngle);
	
	//计算旋转角度的余弦
	fCosa = (float) cos((double)fRotateAngle);
	
	//计算原图的四个角的坐标(以图像中心为坐标系原点)
	fSrcX1 = (float) (- (nOldWidth  - 1) / 2);
	fSrcY1 = (float) (  (nOldHeight - 1) / 2);
	fSrcX2 = (float) (  (nOldWidth  - 1) / 2);
	fSrcY2 = (float) (  (nOldHeight - 1) / 2);
	fSrcX3 = (float) (- (nOldWidth  - 1) / 2);
	fSrcY3 = (float) (- (nOldHeight - 1) / 2);
	fSrcX4 = (float) (  (nOldWidth  - 1) / 2);
	fSrcY4 = (float) (- (nOldHeight - 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;
	
	//计算旋转后的图像实际宽度
	int nNewWidth  = (long) ( max( fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2) ) + 0.5);
	
	//计算旋转后的图像高度
	int nNewHeight = (long) ( max( fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2) )  + 0.5);
	
	//两个常数
	f1 = (float) (-0.5 * (nNewWidth - 1) * fCosa - 0.5 * (nNewHeight - 1) * fSina
		+ 0.5 * (nOldWidth  - 1));
	f2 = (float) ( 0.5 * (nNewWidth - 1) * fSina - 0.5 * (nNewHeight - 1) * fCosa
		+ 0.5 * (nOldHeight - 1));

	//定义变量
	unsigned char *pOldBuffer, *pNewBuffer; 
	unsigned char *pOldBits, *pNewBits;
	unsigned char *pOldTemp, *pNewTemp;
	BITMAPFILEHEADER *pOldBFH, *pNewBFH;
	BITMAPINFOHEADER *pOldBIH, *pNewBIH;
	RGBQUAD *pOldPalette, *pNewPalette;
	int nOldWidthBytes, nNewWidthBytes, nNumColors, x, y;

	//原图像指针
	pOldBuffer = (unsigned char *) 
				m_pDibObject->GetDIBPointer( &nOldWidthBytes, 
				m_pDibObject->GetNumBits(), 
				&nNewWidthBytes, nNewWidth );
	if( pOldBuffer == NULL ) return( FALSE );

	//原图像文件头指针
	pOldBFH = (BITMAPFILEHEADER *) pOldBuffer;
	//原图像信息头指针
	pOldBIH = (BITMAPINFOHEADER *) 
			&pOldBuffer[sizeof(BITMAPFILEHEADER)];
	//原图像颜色数
	nNumColors = m_pDibObject->GetNumColors();
	//原图像调色板指针
	pOldPalette = (RGBQUAD *) &pOldBuffer[sizeof(BITMAPFILEHEADER)
									+sizeof(BITMAPINFOHEADER)];
	//原图像数据指针
	pOldBits = (unsigned char *)
				&pOldBuffer[sizeof(BITMAPFILEHEADER)
				+sizeof(BITMAPINFOHEADER)
				+nNumColors*sizeof(RGBQUAD)];

	DWORD dwNewSize;
	HGLOBAL hNewDib;

	//新图像大小(包括文件头、信息头、调色板和图像数据)
	dwNewSize = (DWORD) nNumColors * sizeof( RGBQUAD ) +
						sizeof( BITMAPFILEHEADER ) + 
						sizeof( BITMAPINFOHEADER ) + 
						nNewWidthBytes * nNewHeight;
	//为新图像分配内存
	hNewDib = ::GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, dwNewSize );
	if( hNewDib == NULL )
	{
		m_pDibObject->m_nLastError = IMAGELIB_MEMORY_ALLOCATION_ERROR;
		::GlobalUnlock( m_pDibObject->GetDib() );
		return( FALSE );
	}

	//新图像指针
	pNewBuffer = (unsigned char *) ::GlobalLock( hNewDib );
	if( pNewBuffer == NULL )
	{
		::GlobalFree( hNewDib );
		m_pDibObject->m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
		::GlobalUnlock( m_pDibObject->GetDib() );
		return( FALSE );
	}

	//新图像文件头指针
	pNewBFH = (BITMAPFILEHEADER *) pNewBuffer;
	//新图像信息头指针
	pNewBIH = (BITMAPINFOHEADER *) &pNewBuffer[sizeof(BITMAPFILEHEADER)];
	//新图像调色板指针
	pNewPalette = (RGBQUAD *) &pNewBuffer[sizeof(BITMAPFILEHEADER)
							+sizeof(BITMAPINFOHEADER)];
	//新图像数据指针
	pNewBits = (unsigned char *) &pNewBuffer[sizeof(BITMAPFILEHEADER)
									+sizeof(BITMAPINFOHEADER)
									+nNumColors*sizeof(RGBQUAD)];

	//用255(白色)填充新图像数据区
	memset(pNewBits, (BYTE)255, nNewWidthBytes * nNewHeight );

	//用原图像文件头数据填充新图像文件头
	memcpy( pNewBFH, pOldBFH, sizeof(BITMAPFILEHEADER) );

	//用原图像信息头数据填充新图像信息头
	memcpy( pNewBIH, pOldBIH, sizeof(BITMAPINFOHEADER) );

	//调整文件总字节数
	pNewBFH->bfSize = dwNewSize;

	//调整新图像的宽度和高度
	pNewBIH->biWidth = nNewWidth;
	pNewBIH->biHeight = nNewHeight;

	//pNewBIH->biBitCount = nNewBitsPerPixel;
	pNewBIH->biSizeImage = nNewWidthBytes * nNewHeight;
	pNewBIH->biClrUsed = nNumColors;
	pNewBFH->bfSize = sizeof( BITMAPFILEHEADER ) 
					+ sizeof( BITMAPINFOHEADER ) 
					+ nNumColors * sizeof( RGBQUAD ) 
					+ pNewBIH->biSizeImage;
	pNewBFH->bfOffBits = sizeof( BITMAPFILEHEADER ) 
						+ sizeof( BITMAPINFOHEADER ) 
						+ nNumColors * sizeof( RGBQUAD );

	//用原图像调色板填充新图像调色板
	if(nNumColors != 0)
		memcpy( pNewPalette, pOldPalette, nNumColors*sizeof(RGBQUAD) );

	//由图像位数确定的移动字节数
	int nMovedBits = 1;
	switch( m_pDibObject->GetNumBits() )
	{
	case 8:	
		nMovedBits = 1;
		break;
	case 16:
		nMovedBits = 2;
		break;
	case 24:
		nMovedBits = 3;
		break;
	case 32:
		nMovedBits = 4;
		break;
	}

	//针对图像每行进行操作
	for(y = 0; y < nNewHeight; y++)
	{
		//指向新图像第y行
		//注意此处宽度和高度是新图像的宽度和高度
		pNewTemp = pNewBits;
		pNewTemp += (nNewHeight - 1 - y) * nNewWidthBytes;
		//针对图像每列进行操作
		for(x = 0; x < nNewWidth; x++)
		{
			//计算该像素在源图像中的坐标
			int y0 = (long) (-((float) x) * fSina + ((float) y)
					* fCosa + f2 + 0.5);
			int x0 = (long) ( ((float) x) * fCosa + ((float) y)
					* fSina + f1 + 0.5);

			//判断是否在源图范围内
			if( (x0 >= 0) && (x0 < nOldWidth) && 
				(y0 >= 0) && (y0 < nOldHeight))
			{
				//用双线性插值
				if(bBilinear)
				{
					unsigned char *pTemp = Interpolation (nOldWidth, nOldHeight, 
						(float)x0, (float)y0, 
						nOldWidthBytes, nMovedBits, pOldBits);
					//复制像素
					memcpy(pNewTemp, pTemp, nMovedBits);
					
					delete [] pTemp ;
				}
				else
				{				
					//指向源图像第y0行,第x0个像素
					//注意此处宽度和高度应该互换
					pOldTemp = pOldBits;
					pOldTemp += (nOldHeight - 1 - y0) * nOldWidthBytes;
					pOldTemp += x0 * nMovedBits;
					
					//复制像素
					memcpy(pNewTemp, pOldTemp, nMovedBits);
				}
			}
			pNewTemp += nMovedBits;
		}
		
	}

	//将内存解锁和将不再使用的内存释放
	::GlobalUnlock( m_pDibObject->GetDib() );
	::GlobalFree( m_pDibObject->GetDib() );
	::GlobalUnlock( hNewDib );
	//将新图像设置为当前图像
	m_pDibObject->SetDib( hNewDib );

	m_pDibObject->ProcessImageHeader();

	return TRUE;
}

////////////////////////////////////////////////////////////////////////
//BOOL Interpolation()  
//----------------------------------------------------------------------
//基本功能:本函数对传入的CDibObject对象中的图像进行旋转操作。如果进行
//			此调整之前没有指定一个CDibObject对象指针,则必须在调整时加
//			以指定。
//----------------------------------------------------------------------
//参数说明:int nWidth		- 源图像宽度(像素数)
//			int nHeight		- 源图像高度(像素数)
//			float x			- 插值元素的x坐标
//			float y			- 插值元素的y坐标
//			int nWidthBytes	- 图像字节宽度
//			int nMovedBits	- 一次移动的字节数
//			LPSTR lpDIBBits	- 指向源DIB图像指针
//----------------------------------------------------------------------
//返	回:unsigned char	- 返回插值计算结果。
//----------------------------------------------------------------------
//注	意:该函数利用双线性插值算法来估算像素值。对于超出图像范围的像素,
//			直接返回255。
////////////////////////////////////////////////////////////////////////
unsigned char *CGeoTrans::Interpolation(int nWidth, 
											int nHeight, 
											float x, 
											float y,
											int nWidthBytes,
											int nMovedBits,
											unsigned char *pBits)
{
	//四个最临近像素的坐标(x1, y1), (x2, y1), (x1, y2), (x2, y2)
	long	x1, x2;
	long	y1, y2;
	
	//四个最临近像素值
	unsigned char	f1, f2, f3, f4;
	
	//二个插值中间值
	unsigned char	f12, f34;
	
	//定义一个值,当像素坐标相差小于改值时认为坐标相同
	float	EXP;
	
	//直方图数据数组
	unsigned char *pData = new unsigned char [nMovedBits];
	int i;

	//赋值
	EXP = (float) 0.0001;
	
	//计算四个最临近像素的坐标
	x1 = (long) x;
	x2 = x1 + 1;
	y1 = (long) y;
	y2 = y1 + 1;

	//根据不同情况分别处理
	if( (x < 0) || (x > nWidth - 1) || (y < 0) || (y > nHeight - 1))
	{
		for(i = 0; i < nMovedBits; i++)
		{
			pData[i] =(unsigned char) 255;
		}
		//要计算的点不在源图范围内,直接返回255。
		return(pData);
	}
	else
	{
		if (fabs(x - nWidth + 1) <= EXP)
		{
			//要计算的点在图像右边缘上
			if (fabs(y - nHeight + 1) <= EXP)
			{
				//要计算的点正好是图像最右下角那一个像素,直接返回该点像素值
				for(i = 0; i < nMovedBits; i++)
				{
					pData[i] = *(pBits + nWidthBytes * (nHeight - 1 - y1) + x1 * nMovedBits + i);
				}

				//返回插值结果
				return(pData);
			}
			else
			{
				//在图像右边缘上且不是最后一点,直接一次插值即可
				for(i = 0; i < nMovedBits; i++)
				{
					f1 = *(pBits + nWidthBytes * (nHeight - 1 - y1) + x1 * nMovedBits + i);
					f3 = *(pBits + nWidthBytes * (nHeight - 1 - y1) + x2 * nMovedBits + i);
					pData[i] =(unsigned char)(f1 + (y -y1) * (f3 - f1));
				}

				//返回插值结果
				return(pData);
			}
		}
		else if (fabs(y - nHeight + 1) <= EXP)
		{
			//要计算的点在图像下边缘上且不是最后一点,直接一次插值即可
			for(i = 0; i < nMovedBits; i++)
			{
				f1 = *(pBits + nWidthBytes * (nHeight - 1 - y1) + x1 * nMovedBits + i);
				f2 = *(pBits + nWidthBytes * (nHeight - 1 - y2) + x1 * nMovedBits + i);
				pData[i] =(unsigned char)(f1 + (x -x1) * (f2 - f1));
			}
			
			//返回插值结果
			return(pData);
		}
		else
		{
			//计算四个最临近像素值
			for(i = 0; i < nMovedBits; i++)
			{
				// 计算四个最临近象素值
				f1 = *(pBits + nWidthBytes * (nHeight - 1 - y1) + x1 * nMovedBits + i);
				f2 = *(pBits + nWidthBytes * (nHeight - 1 - y2) + x1 * nMovedBits + i);
				f3 = *(pBits + nWidthBytes * (nHeight - 1 - y1) + x2 * nMovedBits + i);
				f4 = *(pBits + nWidthBytes * (nHeight - 1 - y2) + x2 * nMovedBits + i);

				//插值1
				f12 = (unsigned char)(f1 + (x - x1) * (f2 - f1));
				
				//插值2
				f34 = (unsigned char)(f3 + (x - x1) * (f4 - f3));

				pData[i] = (unsigned char)(f12 + (y -y1) * (f34 - f12));
				//char s[200];
				//wsprintf(s,"pData[%d]=%d", i, pData[i]);
				//AfxMessageBox(s);
			}
			
			//返回插值结果
			return(pData);
		}
	}
}

⌨️ 快捷键说明

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