📄 grayproc.cpp
字号:
int ns_r[256];
int ns_g[256];
int ns_b[256];
// 灰度分布概率
float ps_r[256];
float ps_g[256];
float ps_b[256];
// 中间临时变量
float temp_r[256];
float temp_g[256];
float temp_b[256];
// 指向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);
// 对灰度密度分布进行统计
GetIntensity(hDIB, ns_r, ns_g, ns_b);
// 对灰度分布概率进行统计
GetIntensity(hDIB, ps_r, ps_g, ps_b);
// 计算原始累计直方图
for (i = 0; i < 256; i++)
{
if (i == 0)
{
temp_r[0] = ps_r[0];
temp_g[0] = ps_g[0];
temp_b[0] = ps_b[0];
}
else
{
temp_r[i] = temp_r[i-1] + ps_r[i];
temp_g[i] = temp_g[i-1] + ps_g[i];
temp_b[i] = temp_b[i-1] + ps_b[i];
}
ps_r[i] = temp_r[i];
ps_g[i] = temp_g[i];
ps_b[i] = temp_b[i];
}
// 计算规定累计直方图
for (i = 0; i < bNum; i++)
{
if (i == 0)
{
temp_r[0] = fpPu[0];
}
else
{
temp_r[i] = temp_r[i-1] + fpPu[i];
}
fpPu[i] = temp_r[i];
}
// 确定映射对应关系
for (i = 0; i < 256; i++)
{
// 最接近的规定直方图灰度级
int m_r = 0;
int m_g = 0;
int m_b = 0;
// 最小差值
float min_value_r = 1.0f;
float min_value_g = 1.0f;
float min_value_b = 1.0f;
// 对规定直方图各灰度进行枚举
for (j = 0; j < bNum; j++)
{
// 当前差值
float now_value = 0.0f;
// 对R分量计算差值
if (ps_r[i] - fpPu[j] >= 0.0f)
now_value = ps_r[i] - fpPu[j];
else
now_value = fpPu[j] - ps_r[i];
// 寻找最接近的规定直方图灰度级
if (now_value < min_value_r)
{
// 最接近的灰度级
m_r = j;
// 暂存最小差值
min_value_r = now_value;
}
// 对G分量计算差值
if (ps_g[i] - fpPu[j] >= 0.0f)
now_value = ps_g[i] - fpPu[j];
else
now_value = fpPu[j] - ps_g[i];
// 寻找最接近的规定直方图灰度级
if (now_value < min_value_g)
{
// 最接近的灰度级
m_g = j;
// 暂存最小差值
min_value_g = now_value;
}
// 对B分量计算差值
if (ps_b[i] - fpPu[j] >= 0.0f)
now_value = ps_b[i] - fpPu[j];
else
now_value = fpPu[j] - ps_b[i];
// 寻找最接近的规定直方图灰度级
if (now_value < min_value_b)
{
// 最接近的灰度级
m_b = j;
// 暂存最小差值
min_value_b = now_value;
}
}
// 建立灰度映射表
ns_r[i] = npNu[m_r];
ns_g[i] = npNu[m_g];
ns_b[i] = npNu[m_b];
}
// 对各像素进行处理
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lLineBytes; j ++)
{
// 对像素各颜色分量进行单映射规则的直方图规定化映射处理
unsigned char R = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
*((unsigned char *)lpDIBBits + lLineBytes * i + j) = ns_r[R];
j++;
unsigned char G = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
*((unsigned char *)lpDIBBits + lLineBytes * i + j) = ns_g[G];
j++;
unsigned char B = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
*((unsigned char *)lpDIBBits + lLineBytes * i + j) = ns_b[B];
}
}
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 恢复光标
EndWaitCursor();
}
/*************************************************************************
*
* 函数名称:
* PointGML()
*
* 参数:
* HDIB hDIB - 待处理的DIB
* BYTE bNum - 规定直方图灰度级数
* int* npNu - 规定直方图灰度映射关系
* float* fpPu - 规定直方图各灰度的分布概率
*
* 返回值:
* void - 无返回值
*
* 说明:
* 该函数对图像进行组映射规则直方图规定化变换
*
************************************************************************/
void CGrayProc::PointGML(HDIB hDIB, BYTE bNum, int *npNu, float *fpPu)
{
// 循环变量
LONG i;
LONG j;
LONG k;
// 灰度分布密度
int ns_r[256];
int ns_g[256];
int ns_b[256];
// 灰度分布概率
float ps_r[256];
float ps_g[256];
float ps_b[256];
// 中间临时变量
float temp_r[256];
float temp_g[256];
float temp_b[256];
// 灰度映射区间的起始灰度
int A1_r = 0;
int A1_g = 0;
int A1_b = 0;
// 灰度映射区间的终止灰度
int A2_r = 0;
int A2_g = 0;
int A2_b = 0;
// 指向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);
// 对灰度密度分布进行统计
GetIntensity(hDIB, ns_r, ns_g, ns_b);
// 对灰度分布概率进行统计
GetIntensity(hDIB, ps_r, ps_g, ps_b);
// 计算原始累计直方图
for (i = 0; i < 256; i++)
{
if (i == 0)
{
temp_r[0] = ps_r[0];
temp_g[0] = ps_g[0];
temp_b[0] = ps_b[0];
}
else
{
temp_r[i] = temp_r[i-1] + ps_r[i];
temp_g[i] = temp_g[i-1] + ps_g[i];
temp_b[i] = temp_b[i-1] + ps_b[i];
}
ps_r[i] = temp_r[i];
ps_g[i] = temp_g[i];
ps_b[i] = temp_b[i];
}
// 计算规定累计直方图
for(i = 0; i < bNum; i++)
{
if(i == 0)
{
temp_r[0] = fpPu[0];
}
else
{
temp_r[i] = temp_r[i-1] + fpPu[i];
}
fpPu[i] = temp_r[i];
}
// 确定映射对应关系
for (i = 0; i < bNum; i++)
{
// 最小差值
float min_value_r = 1.0f;
float min_value_g = 1.0f;
float min_value_b = 1.0f;
// 对原始直方图分布进行枚举检索
for (j = 0; j < 256; j++)
{
// 当前差值
float now_value = 0.0f;
// 对R分量计算差值
if (ps_r[j] - fpPu[i] >= 0.0f)
now_value = ps_r[j] - fpPu[i];
else
now_value = fpPu[i] - ps_r[j];
// 寻找最接近的规定直方图灰度级
if (now_value < min_value_r)
{
// 最接近的灰度级
A2_r=j;
// 暂存最小差值
min_value_r = now_value;
}
// 对G分量计算差值
if (ps_g[j] - fpPu[i] >= 0.0f)
now_value = ps_g[j] - fpPu[i];
else
now_value = fpPu[i] - ps_g[j];
// 寻找最接近的规定直方图灰度级
if (now_value < min_value_g)
{
// 最接近的灰度级
A2_g = j;
// 暂存最小差值
min_value_g = now_value;
}
// 对B分量计算差值
if (ps_b[j] - fpPu[i] >= 0.0f)
now_value = ps_b[j] - fpPu[i];
else
now_value = fpPu[i] - ps_b[j];
// 寻找最接近的规定直方图灰度级
if (now_value < min_value_b)
{
// 最接近的灰度级
A2_b = j;
// 暂存最小差值
min_value_b = now_value;
}
}
// 将[A1_r,A2_r]区间的原始灰度k通过建立映射表ns_r[]映射到灰度nu[i]
for (k = A1_r; k <= A2_r; k++)
ns_r[k] = npNu[i];
// 移动区间其始位置
A1_r = A2_r + 1;
// 将[A1_g,A2_g]区间的原始灰度k通过建立映射表ns_g[]映射到灰度nu[i]
for (k = A1_g; k <= A2_g; k++)
ns_g[k] = npNu[i];
// 移动区间其始位置
A1_g = A2_g + 1;
// 将[A1_b,A2_b]区间的原始灰度k通过建立映射表ns_b[]映射到灰度nu[i]
for (k = A1_b; k <= A2_b; k++)
ns_b[k] = npNu[i];
// 移动区间其始位置
A1_b = A2_b + 1;
}
// 对各像素进行处理
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lLineBytes; j ++)
{
// 对像素各颜色分量进行单映射规则的直方图规定化映射处理
unsigned char R = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
*((unsigned char *)lpDIBBits + lLineBytes * i + j) = ns_r[R];
j++;
unsigned char G = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
*((unsigned char *)lpDIBBits + lLineBytes * i + j) = ns_g[G];
j++;
unsigned char B = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
*((unsigned char *)lpDIBBits + lLineBytes * i + j) = ns_b[B];
}
}
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 恢复光标
EndWaitCursor();
}
/*************************************************************************
*
* 函数名称:
* DynamicCompress()
*
* 参数:
* HDIB hDIB - 待处理的DIB
* float fC - 尺度比例常数
*
* 返回值:
* void - 无返回值
*
* 说明:
* 该函数对图像进行灰度动态范围压缩处理
*
************************************************************************/
void CGrayProc::DynamicCompress(HDIB hDIB, int nC)
{
// 循环变量
LONG i;
LONG j;
// 指向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);
// 对各像素进行灰度转换
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lLineBytes; j ++)
{
// 对像素各颜色分量进行灰度动态范围压缩
unsigned char R = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
R = (unsigned char)(nC * log(1 + R));
*((unsigned char *)lpDIBBits + lLineBytes * i + j) = R;
j++;
unsigned char G = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
G = (unsigned char)(nC * log(1 + G));
*((unsigned char *)lpDIBBits + lLineBytes * i + j) = G;
j++;
unsigned char B = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
B = (unsigned char)(nC * log(1 + B));
*((unsigned char *)lpDIBBits + lLineBytes * i + j) = B;
}
}
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 恢复光标
EndWaitCursor();
}
/*************************************************************************
*
* 函数名称:
* CutWave()
*
* 参数:
* HDIB hDIB - 待处理的DIB
*
* 返回值:
* void - 无返回值
*
* 说明:
* 该函数将对图象进行灰度削波处理
*
************************************************************************/
void CGrayProc::CutWave(HDIB hDIB)
{
// 循环变量
LONG i;
LONG j;
// 指向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);
// 对各像素进行灰度转换
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lLineBytes; j ++)
{
// 获取各颜色分量
unsigned char B = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
j++;
unsigned char G = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
j++;
unsigned char R = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
// 计算灰度值
unsigned char Y = (9798 * R + 19235 * G + 3735 * B) / 32768;
if (Y < 30)
{
R = G = B = 0;
}
if (Y >= 30 && Y < 200)
{
R = R * 256 / 200;
G = G * 256 / 200;
B = B * 256 / 200;
// 超限保护
if (R > 255) R = 255;
if (R < 0) R = 0;
if (G > 255) G = 255;
if (G < 0) G = 0;
if (B > 255) B = 255;
if (B < 0) B = 0;
}
if (Y >= 200)
{
R = G = B = 255;
}
// 回写灰度值
*((unsigned char *)lpDIBBits + lLineBytes * i + j - 2) = B;
*((unsigned char *)lpDIBBits + lLineBytes * i + j - 1) = G;
*((unsigned char *)lpDIBBits + lLineBytes * i + j ) = R;
}
}
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 恢复光标
EndWaitCursor();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -