加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

opencv结合MFC显示带滚动条的大图片

(2012-12-18 19:41:29)
标签:

opencv

mfc

滚动条

大图

分类: ITprogrammer
参考 http://blog.csdn.net/ixzf2009/article/details/6564456 的内容,结合自己的实际情况,实现了在MFC中显示IplImage 的大图片。

 http://s1/mw690/8154bb46t02b367313a00&690
1. 工程是在VS2010中的基于对话框的MFC工程。
我最开始的思路是创建一个CStatic的图片控件,为其添加滚动条,发现无法实现。
此工程中的思路是创建一个BUTTON,通过为BUTTON添加背景图案来实现。
下面进行必要的流程阐述和相关代码。
A。新建一个继承自CBUTTON的ButtonPic类。
在ButtonPic.h中添加变量和函数声明

// Attributes
public:

    int m_nHorzPos;
    int m_nVertPos;
    int m_nHorzMaxSize;
    int m_nVertMaxSize;
    int m_nHorzPageSize;
    int m_nVertPageSize;
    int m_nOneStep;
    CBitmap *cb;
public:
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    void InitPic(int nStep,CBitmap *cbmp);
    void DarwPic();

B。 在对话框中添加一个BUTTON,为其关联变量,注意,变量类型需要为ButtonPic,此处变量名为m_cbtnPic
在 BOOL CDispScrollDlg::OnInitDialog()中添加代码:

// TODO: Add extra initialization here
    m_cbtnPic.ShowScrollBar(SB_BOTH);
    CDC* pDC = this ->GetDC();        // 获得显示控件的 DC
    HDC hDC = pDC ->GetSafeHdc();                // 获取 HDC(设备句柄) 来进行绘图操作
    IplImage *image=cvLoadImage("lena.jpg");
    CBitmap *cbmp=IplImage2CBitmap(image);
    m_cbtnPic.InitPic(10,cbmp);

此处IplImage2CBitmap是用来将IplImage类型转成CBitmap类型。
代码为:
CBitmap * CDispScrollDlg::IplImage2CBitmap(const IplImage *pImage)
{
    if( pImage && pImage->depth == IPL_DEPTH_8U )
    {
        HDC hDC=this->GetDC()->GetSafeHdc();
        uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];
        BITMAPINFO* bmi = (BITMAPINFO*)buffer;
        int bmp_w = pImage->width, bmp_h = pImage->height;
        FillBitmapInfo( bmi, bmp_w, bmp_h, pImage->depth*pImage->nChannels, pImage->origin );

        char *pBits=NULL;
        HBITMAP hBitmap=CreateDIBSection(hDC,bmi,DIB_RGB_COLORS,(void**)&pBits,NULL,0);
        memcpy(pBits,pImage->imageData,pImage->imageSize);
        CBitmap *pBitmap=new CBitmap;
        pBitmap->Attach(hBitmap);

        return pBitmap;
    }
    else
        return NULL;
}

void CDispScrollDlg::FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp, int origin)
{
    assert( bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32));

    BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);

    memset( bmih, 0, sizeof(*bmih));
    bmih->biSize = sizeof(BITMAPINFOHEADER);
    bmih->biWidth = width;
    bmih->biHeight = origin ? abs(height) : -abs(height);
    bmih->biPlanes = 1;
    bmih->biBitCount = (unsigned short)bpp;
    bmih->biCompression = BI_RGB;

    if( bpp == 8 )
    {
        RGBQUAD* palette = bmi->bmiColors;
        int i;
        for( i = 0; i < 256; i++ )
        {
            palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
            palette[i].rgbReserved = 0;
        }
    }
}
ButtonPic.cpp 的代码贴在下方。
注意,其中两个函数OnVScroll,OnHScroll需要通过类向导建立。是用来控制滚动条的。
// ButtonPic.cpp : implementation file
//

#include "stdafx.h"
#include "DispScroll.h"
#include "ButtonPic.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CButtonPic

CButtonPic::CButtonPic()
{
   
}

CButtonPic::~CButtonPic()
{
}


BEGIN_MESSAGE_MAP(CButtonPic, CButton)
    //{{AFX_MSG_MAP(CButtonPic)
    ON_WM_HSCROLL()
    ON_WM_VSCROLL()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CButtonPic message handlers

void CButtonPic::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    // TODO: Add your code to draw the specified item
    DarwPic();
}

void CButtonPic::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // TODO: Add your message handler code here and/or call default
    switch(nSBCode)
    {
        case SB_LEFT:

            m_nHorzPos = 0;
            this->SetScrollPos(SB_HORZ,m_nHorzPos);
            DarwPic();

            break;
        case SB_LINELEFT:
        case SB_PAGELEFT:

            m_nHorzPos -= m_nOneStep;

            if(m_nHorzPos<0)
            {
                m_nHorzPos = 0;
            }
            this->SetScrollPos(SB_HORZ,m_nHorzPos);
            DarwPic();

            break;
        case SB_LINERIGHT:
        case SB_PAGERIGHT:

            m_nHorzPos += m_nOneStep;

            if(m_nHorzPos>m_nHorzMaxSize)
            {
                m_nHorzPos = m_nHorzMaxSize;
            }
            this->SetScrollPos(SB_HORZ,m_nHorzPos);
            DarwPic();

            break;
        case SB_RIGHT:

            m_nHorzPos = m_nHorzMaxSize;
            this->SetScrollPos(SB_HORZ,m_nHorzPos);
            DarwPic();

            break;
        case SB_THUMBPOSITION:
        case SB_THUMBTRACK:

            m_nHorzPos = nPos;
            this->SetScrollPos(SB_HORZ,m_nHorzPos);
            DarwPic();

            break;
        default:
            break;
    }
   
    CButton::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CButtonPic::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // TODO: Add your message handler code here and/or call default
    switch(nSBCode)
    {
        case SB_LEFT:

            m_nVertPos = 0;
            this->SetScrollPos(SB_VERT,m_nVertPos);
            DarwPic();

            break;
        case SB_LINELEFT:
        case SB_PAGELEFT:

            m_nVertPos -= m_nOneStep;

            if(m_nVertPos<0)
            {
                m_nVertPos = 0;
            }
            this->SetScrollPos(SB_VERT,m_nVertPos);
            DarwPic();

            break;
        case SB_LINERIGHT:
        case SB_PAGERIGHT:

            m_nVertPos += m_nOneStep;

            if(m_nVertPos>m_nVertMaxSize)
            {
                m_nVertPos = m_nVertMaxSize;
            }
            this->SetScrollPos(SB_VERT,m_nVertPos);
            DarwPic();

            break;
        case SB_RIGHT:

            m_nVertPos = m_nVertMaxSize;
            this->SetScrollPos(SB_VERT,m_nVertPos);
            DarwPic();

            break;
        case SB_THUMBPOSITION:
        case SB_THUMBTRACK:

            m_nVertPos = nPos;
            this->SetScrollPos(SB_VERT,m_nVertPos);
            DarwPic();

            break;
        default:
            break;
    }
   
    CButton::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CButtonPic::InitPic(int nStep,CBitmap *cbmp)
{
    BITMAP bm;
    CRect rc;
    LPSCROLLINFO  lpsi;
    lpsi = new SCROLLINFO;

    this->GetClientRect(&rc);

    cbmp->GetBitmap(&bm);

    m_nHorzMaxSize = bm.bmWidth;
    m_nVertMaxSize = bm.bmHeight;

    m_nHorzPageSize = rc.Width();
    m_nVertPageSize = rc.Height();

    m_nOneStep = nStep;
    m_nHorzPos = 0;
    m_nVertPos = 0;

    this->SetScrollRange( SB_HORZ,0,m_nHorzMaxSize);
    this->SetScrollRange( SB_VERT,0,m_nVertMaxSize);
    this->GetScrollInfo(SB_HORZ,lpsi);
    lpsi->nPage = m_nHorzPageSize;
    this->SetScrollInfo(SB_HORZ,lpsi);
    this->GetScrollInfo(SB_VERT,lpsi);
    lpsi->nPage = m_nVertPageSize;
    this->SetScrollInfo(SB_VERT,lpsi);
    cb=cbmp;
}

void CButtonPic::DarwPic()
{
    CDC* pDC = this->GetDC();
    CRect rc;

    this->GetClientRect(&rc);

    BITMAP bm;


    cb->GetBitmap(&bm);
    CDC dcImage;

    dcImage.CreateCompatibleDC(pDC);
    dcImage.SelectObject(cb);

    //画图
    //pDC->BitBlt(0,0,bm.bmWidth,bm.bmHeight,&dcImage,0,0,SRCCOPY);
    pDC->StretchBlt(0,0,rc.Width(),rc.Height(), &dcImage,m_nHorzPos ,m_nVertPos,rc.Width(),rc.Height(),SRCCOPY);
}
这样就能实现在MFC中显示较大的IplImage的图片了。
我已将代码放在CSDN上,同学们可以通过下面网址进行下载
http://download.csdn.net/detail/kaizibaby1208/4903387
最后的效果图为:
http://s11/mw690/8154bb46td11f7fb6eb3a&690


0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有