您的位置:首页 > 运维架构

Opencv (Opencv2)结合MFC学习数字图像处理---图片解码(3)

2013-03-26 16:55 971 查看
3. 将图片显示在窗口DC




1 Mat & image = pDoc->src_image;

2 if (image.empty())

3 {

4 return;

5 }

6 CImage cimage;

7 ImageUtility::MatToCImage(image,cimage);

8 cimage.Draw(pDC->GetSafeHdc(),0,0,cimage.GetWidth(),cimage.GetHeight(),

9 0,0,cimage.GetWidth(),cimage.GetHeight());






终于图片可以显示出来了,如下图:






【fit图片到窗口大小】

从上面的结果来看,显示是显示出来了,但是效果不好,因为图片比较大,超过了窗口大小,所以在绘制时,需要做一个缩放,缩放到适合窗口显示的大小,缩放之前,需要先得到窗口大小。

1. override CImageProcessView的OnSize




1 void CImageProcessView::OnSize(UINT nType, int cx, int cy)

2 {

3 nWidth = cx;

4 nHeight = cy;

5 CView::OnSize(nType, cx, cy);

6 // TODO: Add your message handler code here

7 }








2. 将图像缩放到适合窗口显示的大小




1 int fixed_width = min(cimage.GetWidth(),nWidth);

2 int fixed_height = min(cimage.GetHeight(),nHeight);

3

4 double ratio_w = fixed_width / (double)cimage.GetWidth();

5 double ratio_h = fixed_height / (double)cimage.GetHeight();

6 double ratio = min(ratio_w,ratio_h);

7

8 int show_width = (int)(ratio * cimage.GetWidth());

9 int show_height = (int)(ratio * cimage.GetHeight());

10 int offsetx = (nWidth - show_width) / 2;

11 int offsety = (nHeight - show_height) / 2;

12 ::SetStretchBltMode(pDC->GetSafeHdc(), COLORONCOLOR);

13 cimage.StretchBlt(pDC->GetSafeHdc(),

14 offsetx,offsety,

15 show_width,show_height,0,0,cimage.GetWidth(),cimage.GetHeight(),

16 SRCCOPY);








这些图片能完整显示了,而且是显示在窗口的中间,如图






【双缓存去闪烁】

当我们resize窗口时,上面的程序会有剧烈的闪动,这谁能受得了了, 为了改进这一体验,我们使用双缓存方案。

1. override CImageProcessView的OnEraseBkgnd

这样就不再画背景画刷到窗口DC了。




1 BOOL CImageProcessView::OnEraseBkgnd(CDC* pDC)

2 {

3 // TODO: Add your message handler code here and/or call default

4 //return CView::OnEraseBkgnd(pDC);

5 return TRUE;

6 }




2. 加入双缓存

首先写一个双缓存类DoubleBufferSys




1 #pragma once

2 #include <windows.h>

3 class DoubleBufferSys

4 {

5 public:

6 DoubleBufferSys();

7 ~DoubleBufferSys();

8 void Resize(int width,int height);

9 void SetCDC(CDC * pDC);

10 CDC& GetMemDC();

11 void Present();

12 private:

13 CDC MemDC; //首先定义一个显示设备对象

14 CBitmap MemBitmap;//定义一个位图对象

15 CDC * pDC;

16 int width;

17 int height;

18

19 };





实现代码如下




1 #include "stdafx.h"

2 #include "DoubleBufferSys.h"

3 DoubleBufferSys::DoubleBufferSys()

4 {

5 MemDC.CreateCompatibleDC(NULL);

6 }

7

8 DoubleBufferSys::~DoubleBufferSys()

9 {

10 MemBitmap.DeleteObject();

11 MemDC.DeleteDC();

12 }

13 void DoubleBufferSys::Present()

14 {

15 pDC->BitBlt(0,0,width,height,&MemDC,0,0,SRCCOPY);

16 }

17 void DoubleBufferSys::Resize(int _width,int _height)

18 {

19 if (_width <=0 || _height <=0)

20 {

21 return;

22 }

23 width = _width;

24 height = _height;

25

26 MemBitmap.DeleteObject();

27 MemBitmap.CreateCompatibleBitmap(pDC,width,height);

28 CBitmap *pOldBit = MemDC.SelectObject(&MemBitmap);

29 MemDC.FillSolidRect(0,0,width,height,RGB(0,0,0));

30 }

31

32 void DoubleBufferSys::SetCDC(CDC *_pDC)

33 {

34 pDC = _pDC;

35 }

36

37 CDC& DoubleBufferSys::GetMemDC()

38 {

39 return MemDC;

40 }




然后在CImageProcessView类中定义一个双缓存系统对象DoubleBufferSys dbbufSys; 并在绘制函数中如下调用




1 dbbufSys.SetCDC(pDC);

2 dbbufSys.Resize(nWidth,nHeight);

3

4 Mat & image = pDoc->src_image;

5 if (image.empty())

6 {

7 dbbufSys.Present();

8 return;

9 }

10

11 .................

12

13 ::SetStretchBltMode(dbbufSys.GetMemDC(), COLORONCOLOR);

14 cimage.StretchBlt(dbbufSys.GetMemDC(),

15 offsetx,offsety,

16 show_width,show_height,0,0,cimage.GetWidth(),cimage.GetHeight(),

17 SRCCOPY);

18

19 dbbufSys.Present();






这样就不会出现讨厌的闪烁了,另外,DoubleBufferSys这个类可以复用,使用时按照如下流程即可

1. 设置CDC指针到DoubleBufferSys

2. Resize 双缓存大小

3. 在双缓存中的缓存中绘制

4. 将缓存中的内容Present(也就是拷贝到)显存





这样,一个比较完整的利用opencv解码jpeg,并在窗口中显示的小程序就完成了,以后可以基于此实现一些数字处理的算法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: