📄 grayprocess.cpp
字号:
//定义一个数组, 大小为256, 记录256级灰度出现的频数
DWORD adwFreqSrc[256];
for(i = 0;i < 256;i++)adwFreqSrc[i] = 0;
BYTE* pbyGrayCopy = pbyGraySubArea;
for(i = 0;i < h;i++)
{
BYTE* pbyRsc = lpbyBits32 + dwBaseIndex;
for(j = 0;j < w;j++)
{
BYTE b = *pbyRsc++;
BYTE g = *pbyRsc++;
BYTE r = *pbyRsc++;
pbyRsc++;
BYTE gray = (BYTE)(((WORD)r * 30 + (WORD)g * 59 + (WORD)b * 11) / 100);
adwFreqSrc[gray]++;
*pbyGrayCopy++ = gray;
}
dwBaseIndex += dwWidthBytes;
}
//完成频率统计工作
//将频数(Frequencies)进行累加
DWORD adwAccumuSrc[256];
adwAccumuSrc[0] = adwFreqSrc[0];
for(i = 1; i < 256; i++)
adwAccumuSrc[i] = adwAccumuSrc[i - 1] + adwFreqSrc[i];
//最后记录均衡后的灰度, 明显地, 其等级少于256或灰度得到提高
for(i = 0; i < 256; i++)
adwAccumuSrc[i] = ((adwAccumuSrc[i] * 255) / dwPixelSize);
//第三步, 灰度修改
//重新开始
dwBaseIndex = y * dwWidthBytes + 4 * x;
pbyGrayCopy = pbyGraySubArea;
for(i = 0;i < h;i++)
{
BYTE* pbyRsc = lpbyBits32 + dwBaseIndex;
for(j = 0;j < w;j++)
{
//原像素的灰度
BYTE byGraySrc = *pbyGrayCopy++;
//原像素的最终灰度
BYTE byGrayDst = (BYTE)adwAccumuSrc[byGraySrc];
*pbyRsc++ = byGrayDst;
*pbyRsc++ = byGrayDst;
*pbyRsc++ = byGrayDst;
pbyRsc++;
}
dwBaseIndex += dwWidthBytes;
}
delete[] pbyGraySubArea;
return TRUE;
}
//直方图规定化, 应用步骤:
//第一, 给定灰度出现的频数, 采用成员函数设定灰度频数, 灰度级必须为256级
//第二, 进行灰度直方图规定化
BOOL CGrayProcess::MakeHistogramMatch(LPBYTE lpbyBits32, int x, int y, int nWidth, int nHeight, int nScanWidth, int nScanHeight)
{
ASSERT(lpbyBits32);
//第一步, 进行参数合法性检测
if(m_pnMatchFreq == NULL) return FALSE;
if((x > (nScanWidth - 1)) || (y > (nScanHeight - 1))) return FALSE;
//有效区域的宽度和高度
int w = min(nWidth, nScanWidth - x);
int h = min(nHeight, nScanHeight - y);
if(w * h == 0)return FALSE;
//第二步, 对原图像灰度进行统计
//行字节数
DWORD dwWidthBytes = (DWORD)nScanWidth * 4;
//开始数据基索引
DWORD dwBaseIndex = y * dwWidthBytes + 4 * x;
//子区域像素个数
DWORD dwPixelSize = w * h;
int i = 0;
int j = 0;
//开辟一个内存区, 记录指定区域的灰度值
//记录子区域的灰度
BYTE* pbyGraySubArea = new BYTE[dwPixelSize];
if(pbyGraySubArea == NULL) return FALSE;
//定义一个数组, 大小为256, 记录256级灰度出现的频数--源
DWORD adwFreqSrc[256];
for(i = 0;i < 256;i++)adwFreqSrc[i] = 0;
BYTE* pbyGrayCopy = pbyGraySubArea;
for(i = 0;i < h;i++)
{
BYTE* pbyRsc = lpbyBits32 + dwBaseIndex;
for(j = 0;j < w;j++)
{
BYTE b = *pbyRsc++;
BYTE g = *pbyRsc++;
BYTE r = *pbyRsc++;
pbyRsc++;
BYTE gray = (BYTE)(((WORD)r * 30 + (WORD)g * 59 + (WORD)b * 11) / 100);
adwFreqSrc[gray]++;
*pbyGrayCopy++ = gray;
}
dwBaseIndex += dwWidthBytes;
}
//完成频率统计工作
//将频数进行累加
DWORD adwAccumSrc[256];
adwAccumSrc[0] = adwFreqSrc[0];
for(i = 1; i < 256; i++)
adwAccumSrc[i] = adwAccumSrc[i - 1] + adwFreqSrc[i];
//最后记录均衡后的灰度, 明显地, 其等级少于256或灰度得到提高
for(i = 0; i < 256; i++)
adwAccumSrc[i] = ((adwAccumSrc[i] * 255) / dwPixelSize);
//第三步, 建立映射.
//首先, 累积规定的频数, 从而获得规定的直方图
DWORD adwAccumDst[256];
adwAccumDst[0] = (DWORD)m_pnMatchFreq[0];
for(i = 1; i < 256; i++)
adwAccumDst[i] = adwAccumDst[i - 1] + (DWORD)m_pnMatchFreq[i];
if(adwAccumDst[255] == 0)adwAccumDst[255] = 1;
for(i = 0; i < 255; i++)
adwAccumDst[i] = ((adwAccumDst[i] * 255) / adwAccumDst[255]);
adwAccumDst[255] = 255;
//建立映射:----一个逆过程
adwAccumSrc[0] = SearchBinary((int*)adwAccumDst, adwAccumSrc[0], 0, 255);
//优化的快速查找方法
for(i = 1;i < 256;i++)
adwAccumSrc[i] = SearchBinary((int*)adwAccumDst, adwAccumSrc[i], adwAccumSrc[i - 1], 255);
//第四步, 灰度修改
//重新开始
dwBaseIndex = y * dwWidthBytes + 4 * x;
pbyGrayCopy = pbyGraySubArea;
for(i = 0;i < h;i++)
{
BYTE* pbyRsc = lpbyBits32 + dwBaseIndex;
for(j = 0;j < w;j++)
{
//原像素的灰度
BYTE byGraySrc = *pbyGrayCopy++;
//原像素的最终灰度
BYTE byGrayDst = (BYTE)adwAccumSrc[byGraySrc];
*pbyRsc++ = byGrayDst;
*pbyRsc++ = byGrayDst;
*pbyRsc++ = byGrayDst;
pbyRsc++;
}
dwBaseIndex += dwWidthBytes;
}
delete[] pbyGraySubArea;
return TRUE;
}
//邻近二分查找, 返回最近索引
//nValue----待查找的值
//nStart----开始序号
//nEnd-----结束序号
int CGrayProcess::SearchBinary(const int* pnArray, int nValue, int nStart, int nEnd)
{
ASSERT(pnArray);
int nLength = nEnd - nStart + 1;
if(nLength == 1)return nStart;
else if(nLength == 2)
{
if(nValue <= pnArray[nStart]) return nStart;
else if(nValue >= pnArray[nStart + 1])return (nStart + 1);
else
{
if((nValue - pnArray[nStart]) < (pnArray[nStart + 1] - nValue))
return nStart;
else
return (nStart + 1);
}
}
//nLength >= 3
else
{
//区间右端点
int nRight = nEnd;
//区间左端点
int nLeft = nStart;
//小于等于左端点的值
if(nValue <= pnArray[nLeft]) return nLeft;
//大于等于右端点的值
if(nValue >= pnArray[nRight]) return nRight;
nRight--;
nLeft++;
//区间中点
int nMiddle = (nRight + nLeft) / 2;
//是否发现适度的区间
BOOL bFound = FALSE;
//返回值
int nReturn = -1;
//待查找之数一定在[nLeft - 1, nRight + 1]区间内
while(!bFound && (nRight >= nLeft))
{
//equal to the middle
if(nValue == pnArray[nMiddle])
{
bFound = TRUE;
nReturn = nMiddle;
}
else if(nValue < pnArray[nMiddle])
{
//找到了
if(nValue >= pnArray[nMiddle - 1])
{
bFound = TRUE;
//比较
if((nValue - pnArray[nMiddle - 1]) < (pnArray[nMiddle] - nValue))
nReturn = nMiddle - 1;
else
nReturn = nMiddle;
}
//没有找到, 不在该区间
else
nRight = nMiddle - 1;
}
//nValue > pnArray[middle]
else
{
//找到了
if(nValue < pnArray[nMiddle + 1])
{
bFound = TRUE;
//比较
if((nValue - pnArray[nMiddle]) < (pnArray[nMiddle + 1] - nValue))
nReturn = nMiddle;
else
nReturn = (nMiddle + 1);
}
//没有找到, 不在该区间
else
nLeft = nMiddle + 1;
}//nValue >= pnArray[middle]
nMiddle = (nRight + nLeft) / 2;
}//end -- while
return nReturn;
}// end -- else -- nLength >= 3
}
//按Wallis and Jong-Sen Lee的方法计算数学期望
int CGrayProcess::GetGrayExpectation(LPBYTE lpbyBits32, int x, int y, int nWidth, int nHeight, int nScanWidth, int nScanHeight)
{
ASSERT(lpbyBits32);
//第一步, 进行参数合法性检测
if((x > (nScanWidth - 1)) || (y > (nScanHeight - 1))) return FALSE;
//有效区域的宽度和高度
int w = min(nWidth, nScanWidth - x);
int h = min(nHeight, nScanHeight - y);
if(w * h == 0)return FALSE;
//第二步, 计算灰度数学期望
//行字节数
DWORD dwWidthBytes = (DWORD)nScanWidth * 4;
//开始数据基索引
DWORD dwBaseIndex = y * dwWidthBytes + 4 * x;
//数学期望累积
int nGrayExpSum = 0;
for(int i = 0;i < h;i++)
{
BYTE* pbyRsc = lpbyBits32 + dwBaseIndex;
for(int j = 0;j < w;j++)
{
BYTE b = *pbyRsc++;
BYTE g = *pbyRsc++;
BYTE r = *pbyRsc++;
pbyRsc++;
BYTE gray = (BYTE)(((WORD)r * 30 + (WORD)g * 59 + (WORD)b * 11) / 100);
nGrayExpSum += gray;
}
dwBaseIndex += dwWidthBytes;
}
m_nExpSrc = (nGrayExpSum / (w * h));
return m_nExpSrc;
}
//进行统计匹配
BOOL CGrayProcess::MakeStatisticMatch(LPBYTE lpbyBits32, int x, int y, int nWidth, int nHeight, int nScanWidth, int nScanHeight)
{
ASSERT(lpbyBits32);
//第一步, 进行参数合法性检测
if((x > (nScanWidth - 1)) || (y > (nScanHeight - 1))) return FALSE;
//有效区域的宽度和高度
int w = min(nWidth, nScanWidth - x);
int h = min(nHeight, nScanHeight - y);
if(w * h == 0)return FALSE;
//第二步, 灰度统计
//行字节数
DWORD dwWidthBytes = (DWORD)nScanWidth * 4;
//开始数据基索引
DWORD dwBaseIndex = y * dwWidthBytes + 4 * x;
//子区域像素个数
DWORD dwPixelSize = w * h;
int i = 0;
int j = 0;
//开辟一个内存区, 记录指定区域的灰度值
BYTE* pbyGraySubArea = new BYTE[dwPixelSize];
if(pbyGraySubArea == NULL) return FALSE;
//记录灰度数学期望(平均值, 按Wallis and Jong-Sen Lee的方法)
int nExpGray = 0;
//求出灰度和数学期望(即, 平均值)
BYTE* pbyGrayCopy = pbyGraySubArea;
for(i = 0;i < h;i++)
{
BYTE* pbyRsc = lpbyBits32 + dwBaseIndex;
for(j = 0;j < w;j++)
{
BYTE b = *pbyRsc++;
BYTE g = *pbyRsc++;
BYTE r = *pbyRsc++;
pbyRsc++;
BYTE gray = (BYTE)(((WORD)r * 30 + (WORD)g * 59 + (WORD)b * 11) / 100);
*pbyGrayCopy++ = gray;
nExpGray += gray;
}
dwBaseIndex += dwWidthBytes;
}
//最后数学期望:
nExpGray /= dwPixelSize;
//第三步, 灰度修改
//重新开始
dwBaseIndex = y * dwWidthBytes + 4 * x;
pbyGrayCopy = pbyGraySubArea;
for(i = 0;i < h;i++)
{
BYTE* pbyRsc = lpbyBits32 + dwBaseIndex;
for(j = 0;j < w;j++)
{
//原像素的灰度
BYTE byGraySrc = *pbyGrayCopy++;
//原像素的最终灰度
int nGrayDst = (m_nPercentage * ((int)byGraySrc - nExpGray)) / 100 + m_nExpDst;
BYTE byGrayDst = (BYTE)(BOUND(nGrayDst, 0, 255));
*pbyRsc++ = byGrayDst;
*pbyRsc++ = byGrayDst;
*pbyRsc++ = byGrayDst;
pbyRsc++;
}
dwBaseIndex += dwWidthBytes;
}
delete[] pbyGraySubArea;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -