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

📄 imagegeometry.cpp

📁 这是一个图像处理的程序,改变参数控制图片的大小
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/////////////////////////////////////////////////////////////////////////////////
//
// ImageGeometry.cpp: implementation of the CImageGeometry class.
//
////////////////////////////////////////////////////////////////////////////////
// 版权所有(2002)
// Copyright(2002)
// 编写者: 向世明
// Author: Xiang Shiming


//图像几何变换

#include "stdafx.h"
#include "ImageGeometry.h"
#include "math.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNAMIC(CImageGeometry, CImageProcess)
CImageGeometry::CImageGeometry()
{
	m_dwOperation = IMAGE_GEOMETRY_TRANSLATE;
	m_dwQuality = IMAGE_GEOMETRY_NEAREST_NEIGHBOR_INTERPOLATE;
}

CImageGeometry::~CImageGeometry()
{

}

#ifdef _DEBUG
void CImageGeometry::Dump(CDumpContext& dc) const
{
	CImageProcess::Dump(dc);
}

void CImageGeometry::AssertValid() const
{
	CImageProcess::AssertValid();
}
#endif


void CImageGeometry::SetQuality(DWORD dwQuality)
{
	m_dwQuality = dwQuality;
}

///lpbySrcXY----传递源像素(x, y)的地址, 
//x, y, 经过反向变换后得到的对应于原图像的象点的坐标
//nScanWidth,  int nScanHeight, 源扫描宽度和扫描高度
PIXELCOLORRGB CImageGeometry::Interpolate(LPBYTE lpbySrcXY,  int x,  int y,  float fu,  float fv,  int nScanWidth,  int nScanHeight)
{
	PIXELCOLORRGB rgb;

	//行字节数, 可以将dwWidthBytes作为参数传递过来
	DWORD dwWidthBytes = (DWORD)nScanWidth * 4;
	
	switch(m_dwQuality)
	{
		case IMAGE_GEOMETRY_NEAREST_NEIGHBOR_INTERPOLATE :
		{
			BYTE* pbySrc = lpbySrcXY;
			rgb.blue = *pbySrc++;
			rgb.green = *pbySrc++;
			rgb.red = *pbySrc++;
			break;
		}
		case IMAGE_GEOMETRY_BILINEAR_INTERPOLATE :
		{
			//相邻的四个像素最右下角点的x, y坐标偏移量
			int nx = 1;
			int ny = 1;
			if((x + 1) > (nScanWidth - 1)) nx = 0;
			if((y + 1) > (nScanHeight - 1)) ny = 0;
			
			//相邻四个像素的像素值
			BYTE abyRed[2][2], abyGreen[2][2], abyBlue[2][2];
			
			//像素点(x, y)的数据位置
			BYTE* pbySrc = lpbySrcXY;
			//获取像素数值.
			//(x, y) = (x, y) + (0, 0)
			abyBlue[0][0] = *pbySrc++;
			abyGreen[0][0] = *pbySrc++;
			abyRed[0][0] = *pbySrc++;
			
			//(x + 1, y) = (x, y) + (1, 0)
			pbySrc = (lpbySrcXY + nx * 4);
			abyBlue[1][0] = *pbySrc++;
			abyGreen[1][0] = *pbySrc++;
			abyRed[1][0] = *pbySrc++;

			
			//指向下一行数据
			BYTE* pbySrcTemp = (lpbySrcXY + ny * dwWidthBytes);

			//(x , y + 1) = (x, y) + (0, 1)
			pbySrc = pbySrcTemp;
			abyBlue[0][1] = *pbySrc++;
			abyGreen[0][1] = *pbySrc++;
			abyRed[0][1] = *pbySrc++;

			//(x + 1, y + 1) = (x, y) + (1, 1)
			pbySrc = pbySrcTemp + (4 * nx);
			abyBlue[1][1] = *pbySrc++;
			abyGreen[1][1] = *pbySrc++;
			abyRed[1][1] = *pbySrc++;
			
			rgb.red = (BYTE)(BOUND(((1 - fu) * (1 - fv) * ((float)abyRed[0][0]) + 
				      (1 - fu) * fv * ((float)abyRed[0][1]) + 
					  fu * (1 - fv) * ((float)abyRed[1][0]) +
					  fu * fv * ((float)abyRed[1][1])), 0, 255));
			rgb.green = (BYTE)(BOUND(((1 - fu) * (1 - fv) * ((float)abyGreen[0][0]) + 
				      (1 - fu) * fv * ((float)abyGreen[0][1]) + 
					  fu * (1 - fv) * ((float)abyGreen[1][0]) +
					  fu * fv * ((float)abyGreen[1][1])), 0, 255));

			rgb.blue = (BYTE)(BOUND(((1 - fu) * (1 - fv) * ((float)abyBlue[0][0]) + 
				      (1 - fu) * fv * ((float)abyBlue[0][1]) + 
					  fu * (1 - fv) * ((float)abyBlue[1][0]) +
					  fu * fv * ((float)abyBlue[1][1])), 0, 255));
			break;
		}
		
		case IMAGE_GEOMETRY_THREE_ORDER_INTERPOLATE :
		{
			//像素坐标
			int xx[4], yy[4];
			//相邻四个像素的像素值
			BYTE abyRed[4][4], abyGreen[4][4], abyBlue[4][4];

			xx[0] = -1;  xx[1] = 0; xx[2] = 1; xx[3] = 2;
			yy[0] = -1;  yy[1] = 0; yy[2] = 1; yy[3] = 2;

			//保证合法
			if((x - 1) < 0) xx[0] = 0;
			if((x + 1) > (nScanWidth - 1)) xx[2] = 0;
			if((x + 2) > (nScanWidth - 1)) xx[3] = ((xx[2] == 0) ? 0 : 1);

			if((y - 1) < 0) yy[0] = 0;
			if((y + 1) > (nScanHeight - 1)) yy[2] = 0;
			if((y + 2) > (nScanHeight - 1)) yy[3] = ((yy[2] == 0) ? 0 : 1);

			//像素点(x, y)的数据位置
			//获取数据
			int i;
			for(i = 0;i < 4;i++)
			{
				//像素点(x, y)的数据位置
				BYTE* pbySrcBase = lpbySrcXY + yy[i] * dwWidthBytes;

				for(int j = 0;j < 4;j++)
				{
					BYTE* pbySrc = pbySrcBase + 4 * xx[j];
					abyBlue[i][j] = *pbySrc++;
					abyGreen[i][j] = *pbySrc++;
					abyRed[i][j] = *pbySrc++;
				}
			}

			//u, v向量
			float afu[4], afv[4];

			afu[0] = Sinxx(1.0f + fu);
			afu[1] = Sinxx(fu);
			afu[2] = Sinxx(1.0f - fu);
			afu[3] = Sinxx(2.0f - fu);

			afv[0] = Sinxx(1.0f + fv);
			afv[1] = Sinxx(fv);
			afv[2] = Sinxx(1.0f - fv);
			afv[3] = Sinxx(2.0f - fv);

			//矩阵乘向量的中间值
			float afRed[4] = {0.0f, 0.0f, 0.0f, 0.0f};
			float afGreen[4] = {0.0f, 0.0f, 0.0f, 0.0f};
			float afBlue[4] = {0.0f, 0.0f, 0.0f, 0.0f};

			for(i = 0;i < 4;i++)
			{
				for(int j = 0;j < 4;j++)
				{
					afRed[i] += afv[j] * abyRed[j][i];
					afGreen[i] += afv[j] * abyGreen[j][i];
					afBlue[i] += afv[j] * abyBlue[j][i];				
				}
			}
			rgb.red = (BYTE)(BOUND((afu[0] * afRed[0] + afu[1] * afRed[1] + afu[2] * afRed[2] + 
						afu[3] * afRed[3]), 0, 255));
			rgb.green = (BYTE)(BOUND((afu[0] * afGreen[0] + afu[1] * afGreen[1] + afu[2] * afGreen[2] + 
						afu[3] * afGreen[3]), 0, 255));
			rgb.blue = (BYTE)(BOUND((afu[0] * afBlue[0] + afu[1] * afBlue[1] + afu[2] * afBlue[2] + 
						afu[3] * afBlue[3]), 0, 255));
			break;
		}
		default : break;
	}//end switch

	return rgb;
}

//该函数计算sin(x) / (x)
float CImageGeometry::Sinxx(float fx)
{
	float fabsx = ABS(fx);
	float fxx = fabsx * fabsx;
	float fxxx = fxx * fabsx;
	if(fabsx < 1.0f) return (1.0f - 2.0f * fxx + fxxx);
	else if(fabsx < 2.0f) 
		return (4.0f - 8.0f * fabsx + 5.0f * fxx - fxxx); 
	else return 0.0f;
}

//lpbyBitsSrc32----传递源像素值, 
//x, y, nWidth,  nHeight, 定义区域的宽度
//nScanWidth,  nScanHeight, 扫描宽度和扫描高度
//lpbyBitsDst32----存放最后缩放后的结果
//nWidthImgDst, nHeightImgDst缩放至多大

BOOL CImageGeometry::Scale(LPBYTE lpbyBitsSrc32,  int x,  int y,  int nWidth,  int nHeight,  int nScanWidth,  int nScanHeight, LPBYTE lpbyBitsDst32, int nWidthImgDst, int nHeightImgDst)
{
	//第一步, 进行参数合法性检测
	ASSERT(lpbyBitsSrc32);
	ASSERT(lpbyBitsDst32);
	ASSERT(nWidthImgDst != 0);
	ASSERT(nHeightImgDst != 0);

	if((x > (nScanWidth - 1)) || (y > (nScanHeight - 1))) return FALSE;

	m_dwOperation = IMAGE_GEOMETRY_SCALE;
	//有效区域的宽度和高度
	int w = min(nWidth, nScanWidth - x);
	int h = min(nHeight, nScanHeight - y);
	


	//注意事项:
	//第一:
	//如果(w <  nWidth), 或者(h <  nHeight)则表示指的区域比能够有效获取数据的区域要大, 
	//这时程序将放大倍数, 使最后缩放的结果总能达到 nWidthImgDst 宽和 nHeightImgDst 高
	
	//第二:	
	//fScalex, fScaley所表示的缩放比为真实缩放比的倒数
	//之所以这样处理是由于, 作一次除法, 总比一次乘法要慢.

	//宽度缩放比
	float fScalex = (float)w / (float)nWidthImgDst;
	float fScaley = (float)h / (float)nHeightImgDst;

	//行字节数
	DWORD dwWidthBytes = (DWORD)nScanWidth * 4;
	//开始数据基索引
	DWORD dwBaseIndex = y * dwWidthBytes + 4 * x;


	//指向目标数据
	BYTE* pbyDst = lpbyBitsDst32;
	//完成变换
	for(int i = 0; i < nHeightImgDst;i++)
	{
		//反向变换后获得的浮点y值
		float fYInverse = i * fScaley;
		//取整
		int yy = (int)fYInverse;

		//坐标差值
		float fv = fYInverse - yy;
		
		//对应于原图像的y坐标
		yy += y;

		BYTE* pbySrc = lpbyBitsSrc32 + yy * dwWidthBytes;

		for(int j = 0;j < nWidthImgDst;j++)
		{
			//反向变换后获得的浮点x值
			float fXInverse = j * fScalex;
			//取整
			int xx = (int)fXInverse;

			//坐标差值
			float fu = fXInverse - xx;
			
			//对应于原图像的y坐标
			xx += x;
					
			//获取数据
			BYTE* pbyCurrent =  pbySrc + 4 * xx;
			PIXELCOLORRGB rgb = Interpolate(pbyCurrent, xx, yy, fu, fv, nScanWidth,  nScanHeight);
			
			*pbyDst++ = rgb.blue;
			*pbyDst++ = rgb.green;
			*pbyDst++ = rgb.red;
	
			//alpha数据由外部填充.
			pbyDst++;	
		}
	}
	return TRUE;
}

//顺时针旋转90度
//包括 n * 360 - 90 度 
//x, y, nWidth,  nHeight-----定义子区域
//lpbyBitsDst32----大小为nWidth * nHeight * 4;
//nScanWidth-------源图像扫描宽度
//nScanHeight------源图像扫描高度
BOOL CImageGeometry::RotateCW90(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_CW_90;

	//行字节数
	DWORD dwWidthBytes = (DWORD)nScanWidth * 4;		//No 10

	//指定区域最后一行第一列处的数据地址.
	BYTE* pbySrcBase = lpbyBitsSrc32 + (y + nHeight - 1) * dwWidthBytes + 4 * x;
	
	//目的地地址
	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;
}

//逆时针旋转90度
//lpbyBitsDst32----大小为nWidth * nHeight * 4;
BOOL CImageGeometry::RotateCCW90(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;

⌨️ 快捷键说明

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