📄 areapro.cpp
字号:
//坐标规整化
m_pDibObject->NormalizeCoordinates( &nX1, &nY1, &nX2, &nY2 );
//获取图像宽度和高度(以像素为单位)
int nWidth = m_pDibObject->GetWidth();
int nHeight = m_pDibObject->GetHeight();
//对边界像素不作处理
if( nX1 < nTempXc ) nX1 = nTempXc;
if( nY1 < nTempYc ) nY1 = nTempYc;
if( nX2 > nWidth - nTempW + nTempXc + 1) nX2 = nWidth - nTempW + nTempXc + 1;
if( nY2 > nHeight - nTempH + nTempYc + 1) nY2 = nHeight - nTempH + nTempYc + 1;
//定义变量
unsigned char *pBuffer, *pBits;
RGBQUAD *pPalette;
int nWidthBytes, nNewWidthBytes, nNumColors;
DWORD dwNewSize;
//获得图像指针
pBuffer = (unsigned char *) m_pDibObject->GetDIBPointer( &nWidthBytes,
m_pDibObject->GetNumBits(),
&nNewWidthBytes, 8);
if( pBuffer == NULL ) return( NULL );
//获得颜色数
nNumColors = m_pDibObject->GetNumColors();
//获得调色板指针
pPalette = (RGBQUAD *) &pBuffer[sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)];
//获得位图数据指针
pBits = (unsigned char *) &pBuffer[sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
+ nNumColors * sizeof(RGBQUAD)];
dwNewSize = nNewWidthBytes * nHeight;
//定义用于存储色相值的临时数组
double *pHue = new double [dwNewSize];
if(pHue == NULL) return(FALSE);
memset(pHue, 0, dwNewSize * sizeof(double));
//定义用于存储饱和度值的临时数组
double *pSaturation = new double [dwNewSize];
if(pSaturation == NULL) return(FALSE);
memset(pSaturation, 0, dwNewSize * sizeof(double));
//定义用于存储亮度值的临时数组
unsigned char *pLight = new unsigned char [dwNewSize];
if(pLight == NULL) return(FALSE);
memset(pLight, 0, dwNewSize * sizeof(unsigned char));
float *fTempArray;
//默认为3×3的高通滤波器1模板
static float fpDefaultArray[] = {-1.0, -1.0, -1.0,
-1.0, 9.0, -1.0,
-1.0, -1.0, -1.0};
//没有传入模板,用默认模板
if( fpArray == NULL ) fTempArray = fpDefaultArray;
//采用传入的模板
else fTempArray = fpArray;
//调用Template操作函数
if(!TemplateOperation(fTempArray, fCoef, nTempW, nTempH, nTempXc, nTempYc,
pBits, nWidthBytes, nX1, nY1, nX2, nY2))
{
return(FALSE);
}
//内存解锁
::GlobalUnlock(m_pDibObject->GetDib());
return( TRUE );
}
////////////////////////////////////////////////////////////////////////
//BOOL MedianFilter()
//----------------------------------------------------------------------
//基本功能:本函数对传入的CDibObject图像对象进行中值滤波。任何未指定的或
// 默认为-1的坐标将被置为图像的边缘值。比如:nX1和nY1会被置为0;
// nX2和nY2会被置为图像的宽和高。对整个图像进行中值滤波的最好方
// 法是不传递任何参数。如果不指定一个CDibObject对象指针,函数将
// 使用原先传入的CDibObject对象指针。
//----------------------------------------------------------------------
//参数说明:int nType 获取中值的方式, 默认为1
// 0——冒泡排序
// 1——数组排序
// int nTempW 窗口的宽度
// int nTempH 窗口的高度
// int nTempXc 窗口的中心元素X坐标
// int nTempYc 窗口的中心元素Y坐标
// int nX1 默认为-1
// int nY1 默认为-1
// int nX2 默认为-1
// int nY2 默认为-1
//
//----------------------------------------------------------------------
//返 回:BOOL
// 成功时返回TRUE,失败时返回FALSE。
//----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
BOOL CAreaPro::MedianFilter(int nType, int nTempW, int nTempH, int nTempXc,
int nTempYc, int nX1, int nY1, int nX2, int nY2)
{
//图像指针为空,无法操作返回
if(m_pDibObject == NULL) return(FALSE);
//对1位及4位图像不作任何操作直接返回
if(m_pDibObject->GetNumBits() != 8)
{
// 提示用户参数设置错误
AfxMessageBox("只支持8位图像,请重新载入!");
// 返回
return( FALSE );
}
//坐标规整化
m_pDibObject->NormalizeCoordinates( &nX1, &nY1, &nX2, &nY2 );
//获取图像宽度和高度(以像素为单位)
int nWidth = m_pDibObject->GetWidth();
int nHeight = m_pDibObject->GetHeight();
//对边界像素不作处理
if( nX1 < nTempXc ) nX1 = nTempXc;
if( nY1 < nTempYc ) nY1 = nTempYc;
if( nX2 >= nWidth - nTempW + nTempXc) nX2 = nWidth - nTempW + nTempXc + 1;
if( nY2 >= nHeight - nTempH + nTempYc) nY2 = nHeight - nTempH + nTempYc + 1;
//定义变量
unsigned char Data;
//定义与图像数据操作有关的变量
unsigned char *pOldBuffer, *pNewBuffer,
*pOldBits, *pNewBits,
*pOldTemp, *pNewTemp,
*pNeighborTemp;
BITMAPFILEHEADER *pOldBFH, *pNewBFH;
BITMAPINFOHEADER *pOldBIH, *pNewBIH;
RGBQUAD *pOldPalette, *pNewPalette;
int nWidthBytes, nNumColors, x, y, i, j;
//获取原图像指针
pOldBuffer = (unsigned char *) m_pDibObject->GetDIBPointer( &nWidthBytes,
m_pDibObject->GetNumBits() );
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 = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) +
nNumColors * sizeof( RGBQUAD ) + nWidthBytes * nHeight;
//为新图像分配内存
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)];
//复制原图像数据到新图像
//复制文件头
memcpy(pNewBFH, pOldBFH, sizeof(BITMAPFILEHEADER));
//复制信息头
memcpy(pNewBIH, pOldBIH, sizeof(BITMAPINFOHEADER));
//复制调色板
for(i = 0; i < nNumColors; i++ ) pNewPalette[i] = pOldPalette[i];
//复制图像数据
memcpy( pNewBits, pOldBits, nWidthBytes * nHeight );
//计算模板的尺寸
int nSize = nTempW * nTempH;
//定义查找中值用的临时数组
unsigned char *pGray = new unsigned char [nTempW * nTempH];
if(pGray == NULL) return( NULL );
memset(pGray, 0, (nSize) * sizeof(unsigned char));
unsigned char nData;
switch(m_pDibObject->GetNumBits())
{
case 8: //8位图像
//行位置
for(y = nY1; y < nY2; y++ )
{
//原图像数据指针定位到起始位置
pOldTemp = pOldBits;
//原图像数据指针定位到图像数据每行的起始零位置
pOldTemp += (nHeight - 1 - y) * nWidthBytes;
//原图像数据指针定位到图像数据每行的起始nX1位置
pOldTemp += nX1;
//新图像数据指针定位到起始位置
pNewTemp = pNewBits;
//新图像数据指针定位到图像数据每行的起始零位置
pNewTemp += (nHeight - 1 - y) * nWidthBytes;
//新图像数据指针定位到图像数据每行的起始nX1位置
pNewTemp += nX1;
//列位置
for(x = nX1; x < nX2; x++)
{
//取出原图像nTempW×nTempH邻域内的像素值
for (i = 0; i < nTempH; i++)
{
for (j = 0; j < nTempW; j++)
{
//数据指针指向当前像素
pNeighborTemp = pOldTemp;
//数据指针指向原图像第y - nTempYc + i行。
pNeighborTemp += nWidthBytes * (nTempYc - i);
//第x - nTempXc + j列像素的指针
pNeighborTemp += (j - nTempXc);
//获取像素值
Data = *pNeighborTemp;
pGray[i*nTempW+j] = ( pOldPalette[Data].rgbRed * 30 +
pOldPalette[Data].rgbGreen * 59 +
pOldPalette[Data].rgbBlue * 11 ) / 100;
}
}
nData = GetMedian(pGray, nSize, nType);
//将计算结果赋于新图像
*pNewTemp = (unsigned char) m_pDibObject->GetNearestIndex(
pNewPalette[nData].rgbRed, pNewPalette[nData].rgbGreen,
pNewPalette[nData].rgbBlue, pNewPalette, nNumColors );
//新旧图像数据指针加1
pOldTemp++;
pNewTemp++;
}
}
break;
}
//释放内存
delete [] pGray;
::GlobalUnlock( m_pDibObject->GetDib() );
::GlobalFree( m_pDibObject->GetDib() );
::GlobalUnlock( hNewDib );
m_pDibObject->SetDib( hNewDib );
return(TRUE);
}
////////////////////////////////////////////////////////////////////////
//BOOL TemplateOperation()
//----------------------------------------------------------------------
//基本功能:该函数用指定的模板(任意大小)来对图像数据区的数据进行模板操
// 作,参数nTempH指定模板的高度,参数nTempW指定模板的宽度,参数
// nTempXc和nTempYc指定模板的中心元素坐标,参数fpArray为指定模
// 板元素数组的指针,fCoef指定模板系数。
//----------------------------------------------------------------------
//参数说明:float *fpArray 指向模板数组的指针
// float fCoef 模板系数
// int nTempW 模板的宽度
// int nTempH 模板的高度
// int nTempXc 模板的中心元素X坐标 ( <= nTempW - 1)
// int nTempYc 模板的中心元素Y坐标 ( <= nTempH - 1)
// unsigned char *pData 图像数据指针
// int nWidthBytes 图像字节宽度
// int nX1 处理区域左边界
// int nY1 处理区域上边界
// int nX2 处理区域右边界
// int nY2 处理区域下边界
//----------------------------------------------------------------------
//返 回:BOOL
// 成功时返回TRUE,失败时返回FALSE。
//----------------------------------------------------------------------
//注 意:此函数声明为保护型,只能在CAreaPro类中使用。
//----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
BOOL CAreaPro::TemplateOperation(float *fpArray, float fCoef,
int nTempW, int nTempH, int nTempXc, int nTempYc,
unsigned char *pData, int nWidthBytes,
int nX1, int nY1, int nX2, int nY2)
{
//获取图像高度(以像素为单位)
int nHeight = m_pDibObject->GetHeight();
//定义变量
unsigned char Data;
//定义与图像数据操作有关的变量
unsigned char *pOldBits, *pNewBits,
*pOldTemp, *pNewTemp,
*pNeighborTemp;
int nNumColors, x, y, i, j;
DWORD dwNewSize;
//原图像颜色数
nNumColors = m_pDibObject->GetNumColors();
//原图像数据指针
pOldBits = pData;
HGLOBAL hNewDib;
//新图像文件大小(以字节为单位)
dwNewSize = nWidthBytes * nHeight;
//为新图像分配内存
hNewDib = ::GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, dwNewSize );
//内存分配失败
if( hNewDib == NULL )
{
m_pDibObject->m_nLastError = IMAGELIB_MEMORY_ALLOCATION_ERROR;
::GlobalUnlock( m_pDibObject->GetDib() );
return( FALSE );
}
//新图像指针
pNewBits = (unsigned char *) ::GlobalLock( hNewDib );
if( pNewBits == NULL )
{
::GlobalFree( hNewDib );
m_pDibObject->m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
return( FALSE );
}
//复制图像数据
memcpy( pNewBits, pOldBits, nWidthBytes * nHeight );
//定义卷积运算中用的临时数组
float *pGray = new float [nTempW * nTempH];
if(pGray == NULL) return( NULL );
memset(pGray, 0, (nTempW * nTempH) * sizeof(float));
//行位置
for(y = nY1; y < nY2; y++ )
{
//原图像数据指针定位到起始位置
pOldTemp = pOldBits;
//原图像数据指针定位到图像数据每行的起始零位置
pOldTemp += (nHeight -1 - y) * nWidthBytes;
//原图像数据指针定位到图像数据每行的起始nX1-1位置
pOldTemp += nX1;
//新图像数据指针定位到起始位置
pNewTemp = pNewBits;
//新图像数据指针定位到图像数据每行的起始零位置
pNewTemp += (nHeight -1 - y) * nWidthBytes;
//新图像数据指针定位到图像数据每行的起始nX1位置
pNewTemp += nX1;
//列位置
for(x = nX1; x < nX2; x++)
{
//取出原图像nTempW×nTempH邻域内的像素值
for (i = 0; i < nTempH; i++)
{
for (j = 0; j < nTempW; j++)
{
//数据指针指向当前像素
pNeighborTemp = pOldTemp;
//数据指针指向原图像第y - nTempYc + i行。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -