本文介绍在MFC框架下,使用opencv的解码函数对图片进行解码,并最终显示到窗口。在此过程中,遇到了图片显示时的大小问题,以及闪烁问题,本文将一一解决。
【显示图片】
1. 在CImageProcessView::OnDraw(CDC* pDC) 中写绘制图片的代码
我们已经打开图片时,利用opencv对图片文件进行了解码,图像数据已经在src_image中持有,现在需要把src_image中的数据绘制到窗口。
1
void CImageProcessView::OnDraw(CDC* pDC)
2 {
3 CImageProcessDoc* pDoc = GetDocument();
4 ASSERT_VALID(pDoc);
5 if (!pDoc)
6 return;
7
8 // TODO: add draw code for native data here
9 Mat & image = pDoc->src_image;
10 }
2 {
3 CImageProcessDoc* pDoc = GetDocument();
4 ASSERT_VALID(pDoc);
5 if (!pDoc)
6 return;
7
8 // TODO: add draw code for native data here
9 Mat & image = pDoc->src_image;
10 }
2. 将Mat转化成CImage
Mat是表示图像数据的一个矩阵,它不能直接绘制到窗口DC,通过google,我发现atl的一个类CImage有绘制到DC的方法,所以只需要把Mat在显示之前先转化成CImage,代码如下:
1
void ImageUtility::MatToCImage( Mat &mat, CImage &cImage)
2 {
3 int width = mat.cols;
4 int height = mat.rows;
5 int channels = mat.channels();
6
7 cImage.Destroy();
8 cImage.Create(width,
9 height,
10 8*channels );
11
12 uchar* ps;
13 uchar* pimg = (uchar*)cImage.GetBits();
14 int step = cImage.GetPitch();
15
16 for ( int i = 0; i < height; ++i)
17 {
18 ps = (mat.ptr<uchar>(i));
19 for ( int j = 0; j < width; ++j )
20 {
21 if ( channels == 1 ) // gray
22 {
23 *(pimg + i*step + j) = ps[j];
24 }
25 else if ( channels == 3 ) // color
26 {
27 for ( int k = 0 ; k < 3; ++k )
28 {
29 *(pimg + i*step + j* 3 + k ) = ps[j* 3 + k];
30 }
31 }
32 }
33 }
34
35 }
2 {
3 int width = mat.cols;
4 int height = mat.rows;
5 int channels = mat.channels();
6
7 cImage.Destroy();
8 cImage.Create(width,
9 height,
10 8*channels );
11
12 uchar* ps;
13 uchar* pimg = (uchar*)cImage.GetBits();
14 int step = cImage.GetPitch();
15
16 for ( int i = 0; i < height; ++i)
17 {
18 ps = (mat.ptr<uchar>(i));
19 for ( int j = 0; j < width; ++j )
20 {
21 if ( channels == 1 ) // gray
22 {
23 *(pimg + i*step + j) = ps[j];
24 }
25 else if ( channels == 3 ) // color
26 {
27 for ( int k = 0 ; k < 3; ++k )
28 {
29 *(pimg + i*step + j* 3 + k ) = ps[j* 3 + k];
30 }
31 }
32 }
33 }
34
35 }
需要注意的是:
// 如果是1个通道的图像(灰度图像) DIB格式才需要对调色板设置
// CImage中内置了调色板,我们要对他进行赋值:if (1 == channels)
{
RGBQUAD* ColorTable;
int MaxColors=256;
//这里可以通过CI.GetMaxColorTableEntries()得到大小(如果你是CI.Load读入图像的话)
ColorTable = new RGBQUAD[MaxColors];
cImage.GetColorTable(0,MaxColors,ColorTable);//这里是取得指针
for (int i=0; i<MaxColors; i++)
{
ColorTable[i].rgbBlue = (BYTE)i;
//BYTE和uchar一回事,但MFC中都用它
ColorTable[i].rgbGreen = (BYTE)i;
ColorTable[i].rgbRed = (BYTE)i;
}
cImage.SetColorTable(0,MaxColors,ColorTable);
delete []ColorTable;
}