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

📄 dibapi.cpp

📁 这个程序能够实现各种模板的中值滤波处理
💻 CPP
📖 第 1 页 / 共 2 页
字号:
 * 参数:
 *   HDIB hDib          - 要保存的DIB
 *   CFile& file        - 保存文件CFile
 *
 * 返回值:
 *   BOOL               - 成功返回TRUE,否则返回FALSE或者CFileException
 *
 * 说明:
 *   该函数将指定的DIB对象保存到指定的CFile中。该CFile由调用程序打开和关闭。
 *
 *************************************************************************/


BOOL WINAPI SaveDIB(HDIB hDib, CFile& file)
{
	// Bitmap文件头
	BITMAPFILEHEADER bmfHdr;
	
	// 指向BITMAPINFOHEADER的指针
	LPBITMAPINFOHEADER lpBI;
	
	// DIB大小
	DWORD dwDIBSize;

	if (hDib == NULL)
	{
		// 如果DIB为空,返回FALSE
		return FALSE;
	}

	// 读取BITMAPINFO结构,并锁定
	lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
	
	if (lpBI == NULL)
	{
		// 为空,返回FALSE
		return FALSE;
	}
	
	// 判断是否是WIN3.0 DIB
	if (!IS_WIN30_DIB(lpBI))
	{
		// 不支持其它类型的DIB保存
		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDib);
		
		// 返回FALSE
		return FALSE;
	}

	// 填充文件头

	// 文件类型"BM"
	bmfHdr.bfType = DIB_HEADER_MARKER;

	// 计算DIB大小时,最简单的方法是调用GlobalSize()函数。但是全局内存大小并
	// 不是DIB真正的大小,它总是多几个字节。这样就需要计算一下DIB的真实大小。
	
	// 文件头大小+颜色表大小
	// (BITMAPINFOHEADER和BITMAPCOREHEADER结构的第一个DWORD都是该结构的大小)
	dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI);
	
	// 计算图像大小
	if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
	{
		// 对于RLE位图,没法计算大小,只能信任biSizeImage内的值
		dwDIBSize += lpBI->biSizeImage;
	}
	else
	{
		// 象素的大小
		DWORD dwBmBitsSize;

		// 大小为Width * Height
		dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;
		
		// 计算出DIB真正的大小
		dwDIBSize += dwBmBitsSize;

		// 更新biSizeImage(很多BMP文件头中biSizeImage的值是错误的)
		lpBI->biSizeImage = dwBmBitsSize;
	}


	// 计算文件大小:DIB大小+BITMAPFILEHEADER结构大小
	bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
	
	// 两个保留字
	bmfHdr.bfReserved1 = 0;
	bmfHdr.bfReserved2 = 0;

	// 计算偏移量bfOffBits,它的大小为Bitmap文件头大小+DIB头大小+颜色表大小
	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize
											  + PaletteSize((LPSTR)lpBI);
	// 尝试写文件
	TRY
	{
		// 写文件头
		file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
		
		// 写DIB头和象素
		file.WriteHuge(lpBI, dwDIBSize);
	}
	CATCH (CFileException, e)
	{
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDib);
		
		// 抛出异常
		THROW_LAST();
	}
	END_CATCH
	
	// 解除锁定
	::GlobalUnlock((HGLOBAL) hDib);
	
	// 返回TRUE
	return TRUE;
}


/*************************************************************************
 *
 * 函数名称:
 *   ReadDIBFile()
 *
 * 参数:
 *   CFile& file        - 要读取得文件文件CFile
 *
 * 返回值:
 *   HDIB               - 成功返回DIB的句柄,否则返回NULL。
 *
 * 说明:
 *   该函数将指定的文件中的DIB对象读到指定的内存区域中。除BITMAPFILEHEADER
 * 外的内容都将被读入内存。
 *
 *************************************************************************/

HDIB WINAPI ReadDIBFile(CFile& file)
{
	BITMAPFILEHEADER bmfHeader;
	DWORD dwBitsSize;
	HDIB hDIB;
	LPSTR pDIB;

	// 获取DIB(文件)长度(字节)
	dwBitsSize = file.GetLength();

	// 尝试读取DIB文件头
	if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
	{
		// 大小不对,返回NULL。
		return NULL;
	}

	// 判断是否是DIB对象,检查头两个字节是否是"BM"
	if (bmfHeader.bfType != DIB_HEADER_MARKER)
	{
		// 非DIB对象,返回NULL。
		return NULL;
	}

	// 为DIB分配内存
	hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
	if (hDIB == 0)
	{
		// 内存分配失败,返回NULL。
		return NULL;
	}
	
	// 锁定
	pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);

	// 读象素
	if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
		dwBitsSize - sizeof(BITMAPFILEHEADER) )
	{
		// 大小不对。
		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDIB);
		
		// 释放内存
		::GlobalFree((HGLOBAL) hDIB);
		
		// 返回NULL。
		return NULL;
	}
	
	// 解除锁定
	::GlobalUnlock((HGLOBAL) hDIB);
	
	// 返回DIB句柄
	return hDIB;
}
/*************************************************************************
 *
 * 函数名称:
 *   CalDistance()
 *
 * 参数:
 *   int *data,int *center,int classnum        
 *
 * 返回值:
 *   double               
 *
 * 说明:
 *   该函数用于计算两个象素在N维空间的距离
 *
 *************************************************************************/
double CalDistance(int data[6],int center[6])
{
	int i,distance[6];
    int dsum;
	dsum=0;
	double redis;
	for(i=0;i<6;i++)
	{
	distance[i]=data[i]-center[i];
	dsum+=distance[i]*distance[i];
	}
	redis=sqrt(dsum*1.0);
	return redis;	  
}
/***************************************************************************
矩阵求逆函数
功  能:	矩阵求逆
输  入:	矩阵a,阶数n。
输  出:	返回0(成功),1(失败),经求逆后,a矩阵为逆矩阵
*****************************************************************************/
int InverseMatrix(int *a, int n)
{
	int *is,*js;
	int i,j,k,l,u,v;
	int temp,max_v;
	is=(int *)malloc(n*sizeof(int));
	js=(int *)malloc(n*sizeof(int));
	if(is==NULL||js==NULL)	return(0);
	for(k=0;k<n;k++)
	{
		max_v=0;
		for(i=k;i<n;i++)
		{
			for(j=k;j<n;j++)
			{
				temp=fabs(a[i*n+j]);
				if(temp>max_v)
				{
					max_v=temp; is[k]=i; js[k]=j;
				}
			}
		}
		if(max_v==0)
		{
			free(is); free(js);
			return(0);
		}
		if(is[k]!=k)
		{
			for(j=0;j<n;j++)
			{
				u=k*n+j; v=is[k]*n+j;
				temp=a[u]; a[u]=a[v]; a[v]=temp;
			}
		}
		if(js[k]!=k)
		{
			for(i=0;i<n;i++)
			{
				u=i*n+k; v=i*n+js[k];
				temp=a[u]; a[u]=a[v]; a[v]=temp;
			}
		}
		l=k*n+k;
		a[l]=1/a[l];
		for(j=0;j<n;j++)
		{
			if(j!=k)
			{
				u=k*n+j;
				a[u]*=a[l];
			}
		}
		for(i=0;i<n;i++)
		{
			if(i!=k)
			{
				for(j=0;j<n;j++)
				{
					if(j!=k)
					{
						u=i*n+j;
						a[u]-=a[i*n+k]*a[k*n+j];
					}
				}
			}
		}
		for(i=0;i<n;i++)
		{
			if(i!=k)
			{
				u=i*n+k;
				a[u]*=-a[l];
			}
		}
	}
	for(k=n-1;k>=0;k--)
	{
		if(js[k]!=k)
		{
			for(j=0;j<n;j++)
			{
				u=k*n+j; v=js[k]*n+j;
				temp=a[u]; a[u]=a[v]; a[v]=temp;
			}
		}
		if(is[k]!=k)
		{
			for(i=0;i<n;i++)
			{
				u=i*n+k; v=i*n+is[k];
				temp=a[u]; a[u]=a[v]; a[v]=temp;
			}
		}
	}
	free(is); free(js);
	return(1);

}



/***************************************************************************
//功  能:	矩阵转置
//输  入:	矩阵a(mxn阶)转置后存在矩阵at(nxm阶)中
//输  出:	void,结果在矩阵at中
*****************************************************************************/
void TransposeMatrix(int *a, int *at, int m, int n)
{
	int i,j;
	for(i=0;i<n;i++)
		for(j=0;j<m;j++)
			*(at+i*m+j)=*(a+j*n+i);
}



/***************************************************************************
//功  能:	矩阵相乘
//输  入:	矩阵a(mxn阶)乘以矩阵b(nxk阶)等于矩阵c(mxk阶)。
//输  出:	void,结果在矩阵c中
*****************************************************************************/
void MultiplyMatrix(int *a, int *b, int *c, int m, int n, int k)
{
	int i,j,ii;
	for(i=0;i<m;i++)
	{
		for(j=0;j<k;j++)
		{
			*(c+i*k+j)=0;
			for(ii=0;ii<n;ii++)
				*(c+i*k+j)=*(c+i*k+j)+*(a+i*n+ii)**(b+ii*k+j);
		}
	}
}
/*************************************************************************
 *
 * 函数名称:
 *   MedianFilter()
 *
 * 参数:
 *   LPSTR lpDIBBits		- 指向源DIB图像指针
 *   LONG  lWidth			- 源图像宽度(象素数)
 *   LONG  lHeight			- 源图像高度(象素数)
 *   int   iFilterH			- 滤波器的高度
 *   int   iFilterW			- 滤波器的宽度
 *   int   iFilterMX		- 滤波器的中心元素X坐标
 *   int   iFilterMY		- 滤波器的中心元素Y坐标
 *
 * 返回值:
 *   BOOL					- 成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数对DIB图像进行中值滤波。
 *
 ************************************************************************/

BOOL WINAPI MedianFilter(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, 
						 int iFilterH, int iFilterW, 
						 int iFilterMX, int iFilterMY)
{
	
	// 指向源图像的指针
	unsigned char*	lpSrc;
	
	// 指向要复制区域的指针
	unsigned char*	lpDst;
	
	// 指向复制图像的指针
	LPSTR			lpNewDIBBits;
	HLOCAL			hNewDIBBits;
	
	// 指向滤波器数组的指针
	unsigned char	* aValue;
	HLOCAL			hArray;
	
	// 循环变量
	LONG			i;
	LONG			j;
	LONG			k;
	LONG			l;
	
	// 图像每行的字节数
	LONG			lLineBytes;
	
	// 计算图像每行的字节数
	lLineBytes = WIDTHBYTES(lWidth * 8);
	
	// 暂时分配内存,以保存新图像
	hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
	
	// 判断是否内存分配失败
	if (hNewDIBBits == NULL)
	{
		// 分配内存失败
		return FALSE;
	}
	
	// 锁定内存
	lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
	
	// 初始化图像为原始图像
	memcpy(lpNewDIBBits, lpDIBBits, lLineBytes * lHeight);
	
	// 暂时分配内存,以保存滤波器数组
	hArray = LocalAlloc(LHND, iFilterH * iFilterW);
	
	// 判断是否内存分配失败
	if (hArray == NULL)
	{
		// 释放内存
		LocalUnlock(hNewDIBBits);
		LocalFree(hNewDIBBits);
		
		// 分配内存失败
		return FALSE;
	}
	
	// 锁定内存
	aValue = (unsigned char * )LocalLock(hArray);
	
	// 开始中值滤波
	// 行(除去边缘几行)
	for(i = iFilterMY; i < lHeight - iFilterH + iFilterMY + 1; i++)
	{
		// 列(除去边缘几列)
		for(j = iFilterMX; j < lWidth - iFilterW + iFilterMX + 1; j++)
		{
			// 指向新DIB第i行,第j个象素的指针
			lpDst = (unsigned char*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j;
			
			// 读取滤波器数组
			for (k = 0; k < iFilterH; k++)
			{
				for (l = 0; l < iFilterW; l++)
				{
					// 指向DIB第i - iFilterMY + k行,第j - iFilterMX + l个象素的指针
					lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i + iFilterMY - k) + j - iFilterMX + l;
					
					// 保存象素值
					aValue[k * iFilterW + l] = *lpSrc;
				}
			}
			
			// 获取中值
			* lpDst = GetMedianNum(aValue, iFilterH * iFilterW);
		}
	}
	
	// 复制变换后的图像
	memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
	
	// 释放内存
	LocalUnlock(hNewDIBBits);
	LocalFree(hNewDIBBits);
	LocalUnlock(hArray);
	LocalFree(hArray);
	
	// 返回
	return TRUE;
}

/*************************************************************************
 *
 * 函数名称:
 *   GetMedianNum()
 *
 * 参数:
 *   unsigned char * bpArray	- 指向要获取中值的数组指针
 *   int   iFilterLen			- 数组长度
 *
 * 返回值:
 *   unsigned char      - 返回指定数组的中值。
 *
 * 说明:
 *   该函数用冒泡法对一维数组进行排序,并返回数组元素的中值。
 *
 ************************************************************************/

unsigned char WINAPI GetMedianNum(unsigned char * bArray, int iFilterLen)
{
	// 循环变量
	int		i;
	int		j;
	
	// 中间变量
	unsigned char bTemp;
	
	// 用冒泡法对数组进行排序
	for (j = 0; j < iFilterLen - 1; j ++)
	{
		for (i = 0; i < iFilterLen - j - 1; i ++)
		{
			if (bArray[i] > bArray[i + 1])
			{
				// 互换
				bTemp = bArray[i];
				bArray[i] = bArray[i + 1];
				bArray[i + 1] = bTemp;
			}
		}
	}
	
	// 计算中值
	if ((iFilterLen & 1) > 0)
	{
		// 数组有奇数个元素,返回中间一个元素
		bTemp = bArray[(iFilterLen + 1) / 2];
	}
	else
	{
		// 数组有偶数个元素,返回中间两个元素平均值
		bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2;
	}
	
	// 返回中值
	return bTemp;
}

/*************************************************************************
 *
 * 函数名称:
 *   CalEntropy()
 *
 * 参数:
 *   LPSTR lpDIBBits		- 指向源DIB图像指针
 *   LONG  lWidth			- 源图像宽度(象素数)
 *   LONG  lHeight			- 源图像高度(象素数)
 *
 * 返回值:
 *   double      - 返回指定数组的中值。
 *
 ************************************************************************/
double CalEntropy(LPSTR lpDIBBits,LONG  lWidth,LONG  lHeight)
{
	int i,j;
	double entropy = 0.0;
	int *array;
	array = new int[256];
	for(i=0;i<256;i++)
		*(array+i)=0;

	long total;
	total = lWidth*lHeight;

	long lLineBytes;
    lLineBytes = WIDTHBYTES(lWidth*8);
    //统计图象中各灰度级出现的次数
	for(i=0;i<lHeight;i++)
		for(j=0;j<lWidth;j++)
		{
			unsigned char *lpdst;
            lpdst = (unsigned char *)lpDIBBits + lLineBytes*i + j;
			array[*lpdst]++;
		}
	for(i=0;i<256;i++)
	{
		double tem=0.0;
		tem = array[i]*1.0/total;
		if(tem!=0)
         entropy += -1*tem*log(tem);
			else continue;
	}
	return entropy;
}

⌨️ 快捷键说明

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