MFC画图像直方图

#define U8_GRAY_LEVEL 256
// 显示直方图
/*
pImgData:图像指针
nImgW:图像宽
nImgH:图像高
nIdHist:显示控件ID(picture control)
*/

INT32 CImageWindowDlg::ShowArrHist(UINT8 *pImgData, int nImgW, int nImgH, int nIdHist)
{
	// 计算直方图
	int pnHist[U8_GRAY_LEVEL] = { 0 };
	getEqualHist(pImgData, nImgW*nImgH, pnHist);
	int pArrTemp[U8_GRAY_LEVEL] = { 0 };
	memcpy(pArrTemp, pnHist, U8_GRAY_LEVEL * sizeof(int));
	int nTemp = 0; // 冒泡法 从高到低排序
	for (int i = 0; i < U8_GRAY_LEVEL; ++i)
	{
		for (int j = U8_GRAY_LEVEL - 1; j > i; --j)
		{
		if (pArrTemp[j] > pArrTemp[j - 1])
			{
				nTemp = pArrTemp[j];
				pArrTemp[j] = pArrTemp[j - 1];
				pArrTemp[j - 1] = nTemp;
			}
		}
	}
	// 选择参考值,一般最大值太大,先从第三个数为参考点
	int nRef = 1;
	if (pArrTemp[2] != 0)
	{
		nRef = pArrTemp[2];
	}
	else if (pArrTemp[1] != 0)
	{
		nRef = pArrTemp[1];
	}
	else if (pArrTemp[0] != 0)
	{
		nRef = pArrTemp[0];
	}
	else
	{
		return FALSE;
	}
	// 绘制的笔
	CPen *pPen = new CPen();
	pPen->CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
	CPen *pPen2 = new CPen();
	pPen2->CreatePen(PS_SOLID, 1, RGB(60, 60, 255));
 	CRect rectHist, rect;
	CString str_Temp;
	GetDlgItem(nIdHist)->GetWindowRect(rectHist);
	ScreenToClient(&rectHist);
	int nLeftMargin = 2;							// 左边空白
	int nRightMargin = nLeftMargin;				// 右边空白	
	int nTopMargin = 5;							// 上部空白
	int nButtomMargin = 20;							// 底部空隙,用于显示刻度
	GetDlgItem(nIdHist)->MoveWindow(rectHist.left, rectHist.top, rectHist.Width(), rectHist.Height(), TRUE);
	//rectHist.InflateRect(0, 0, nLeftMargin + nRightMargin + 255 - rectHist.Width(), 0);	// 增加宽和高
	CWnd *pWnd = GetDlgItem(nIdHist);
	pWnd->GetClientRect(&rect);
	CDC *pDCHist = pWnd->GetDC();
	CGdiObject *pPenOld = pDCHist->SelectObject(pPen);
	int i = 0;						// 循环变量
	int nW = rectHist.Width();
	int nH = rectHist.Height();
	int nYmaxPx = nLeftMargin;		// Y坐标轴最大值的位置的横坐标
	int nYmaxPy = nTopMargin;
	int nXmaxPx = rectHist.Width() - nRightMargin;
	int nXmaxPy = rectHist.Height() - nButtomMargin;
	int pnXPx[10] = { 0 };			// X轴刻度位置
	int pnXPx10[30] = { 0 };		// X轴刻度位置,10一个刻度
	int pnYPx[10] = { 0 };			// Y轴刻度位置		
	int nSacle = 256 / 50 + 1;		// 多少个刻度
	int nSacle10 = 256 / 10 + 1;	// 多少个小刻度
	int nSacleY = 4;
	for (i = 0; i < nSacle; ++i)
	{
		pnXPx[i] = nLeftMargin + (rectHist.Width() - nRightMargin - nLeftMargin) * i * 50 / 255;	// X轴刻度位置						
	}
	pnXPx[i] = rectHist.Width() - nRightMargin;
	for (i = 0; i < nSacle10; ++i)
	{
		pnXPx10[i] = nLeftMargin + (rectHist.Width() - nRightMargin - nLeftMargin) * i * 10 / 255;	// X轴刻度位置						
	}
	pnXPx10[i] = rectHist.Width() - nRightMargin;
	for (i = 0; i <= nSacleY; ++i)
	{
		pnYPx[i] = nTopMargin + (rectHist.Height() - nButtomMargin - nTopMargin) * i / nSacleY;		// Y轴刻度位置
	}

	pDCHist->Rectangle(0, 0, rectHist.Width() + 1, rectHist.Height());      //画一个矩形框
	pDCHist->MoveTo(nLeftMargin, rectHist.Height() - nButtomMargin);
	pDCHist->LineTo(rectHist.Width() - nRightMargin, rectHist.Height() - 	nButtomMargin);
	for (i = 1; i < nSacle - 1; i++)
	{
		str_Temp.Format(_T("%d"), i * 50);
		pDCHist->TextOut(pnXPx[i] - 12, nXmaxPy + 2, str_Temp);
	}
	pDCHist->TextOut(pnXPx[0] + 1, nXmaxPy + 2, _T("0"));
	pDCHist->TextOut(pnXPx[i] - 20, nXmaxPy + 2, _T("250"));
	for (i = 1; i <= nSacle; i++)
	{
		pDCHist->MoveTo(pnXPx[i], nXmaxPy + 3);		//绘制X轴刻度				
		pDCHist->LineTo(pnXPx[i], nXmaxPy - 3);
	}
	for (i = 1; i <= nSacle10; i++)
	{
		pDCHist->MoveTo(pnXPx10[i], nXmaxPy + 1);	//绘制X轴的小刻度				
		pDCHist->LineTo(pnXPx10[i], nXmaxPy - 2);
	}
	// 绘制Y轴
	pDCHist->MoveTo(nLeftMargin, nTopMargin);
	pDCHist->LineTo(nLeftMargin, rectHist.Height() - nButtomMargin);
	for (i = 0; i < nSacleY; i++)
	{
		pDCHist->MoveTo(nYmaxPx, pnYPx[i]);							//写Y轴刻度线
		pDCHist->LineTo(nYmaxPx + 3, pnYPx[i]);
	}
	str_Temp.Format(_T("%d"), nRef);
	pDCHist->TextOut(pnYPx[0] + 1, nTopMargin - 4, str_Temp);
	// 显示直方图
	pDCHist->SelectObject(pPen2);
	for (i = 0; i < U8_GRAY_LEVEL; i++)
	{
		int nPx = nLeftMargin + (rectHist.Width() - nRightMargin - nLeftMargin) * (i) / 255;
		int nPy1 = rectHist.Height() - nButtomMargin;
		int nPy2 = nPy1 - (nPy1 - nTopMargin) * pnHist[i] / nRef;
		nPy2 = nPy2 > nTopMargin ? nPy2 : nTopMargin;			// 防止溢出	
																//nPy2 = nPy2 > nTopMargin ? nPy2 : 0;			// 防止溢出		
		pDCHist->MoveTo(nPx, nPy1);
		pDCHist->LineTo(nPx, nPy2);
	}
	pDCHist->SelectObject(pPenOld);
	delete pPen;
	delete pPen2;
	ReleaseDC(pDCHist);

	return TRUE;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_SimpleLife

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值