MFC中使用Picture Control控件显示OpenCV图像几种方法

摘要:
//IDM_ ABOUTBOX必须在系统命令范围内。

本文参考自https://blog.csdn.net/byxdaz/article/details/88091164

本人测试代码如下:

// ShowImageInMFCDlg.h : 头文件
//

#pragma once
#include <vector>
#include <string>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;

// CShowImageInMFCDlg 对话框
class CShowImageInMFCDlg : public CDialogEx
{
// 构造
public:
    CShowImageInMFCDlg(CWnd* pParent = NULL);    // 标准构造函数

// 对话框数据
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_SHOWIMAGEINMFC_DIALOG };
#endif

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持


// 实现
protected:
    HICON m_hIcon;

    // 生成的消息映射函数
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnBnClickedBtnReadimg();

private:
    CRect m_rectPic;

    // 方法1:将opencv的显示窗口与MFC的控件链接起来,效果是opencv的窗口恰好覆盖在控件
    HWND hNameWindowParent = nullptr;
    bool showImage(const std::string &cvWindowName, UINT nControlID, cv::Mat mat, bool bRoomToControlSize = false);
    bool detachWindow(const std::string &cvWindowName, HWND hNameWindowParent);
    bool attachWindow(const std::string &cvWindowName, HWND &hNameWindowParent, UINT nControlID);

    // 方法2:使用CvvImage类

    // 方法3:MFC的绘图函数,将opencv图像数据先copy到缓冲区然后在控件上绘制处理
    void DrawMat(cv::Mat &img, UINT nControlID, bool bRoomToControlSize = false);
public:
    afx_msg void OnBnClickedBtnRaed2();
    afx_msg void OnBnClickedBtnRaed3();
};
// ShowImageInMFCDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "ShowImageInMFC.h"
#include "ShowImageInMFCDlg.h"
#include "afxdialogex.h"
#include "CvvImage.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
    CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_ABOUTBOX };
#endif

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
    DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CShowImageInMFCDlg 对话框



CShowImageInMFCDlg::CShowImageInMFCDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_SHOWIMAGEINMFC_DIALOG, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CShowImageInMFCDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CShowImageInMFCDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_BTN_READIMG, &CShowImageInMFCDlg::OnBnClickedBtnReadimg)
    ON_BN_CLICKED(IDC_BTN_RAED2, &CShowImageInMFCDlg::OnBnClickedBtnRaed2)
    ON_BN_CLICKED(IDC_BTN_RAED3, &CShowImageInMFCDlg::OnBnClickedBtnRaed3)
END_MESSAGE_MAP()


// CShowImageInMFCDlg 消息处理程序

BOOL CShowImageInMFCDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // 将“关于...”菜单项添加到系统菜单中。

    // IDM_ABOUTBOX 必须在系统命令范围内。
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        BOOL bNameValid;
        CString strAboutMenu;
        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
        ASSERT(bNameValid);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
    //  执行此操作
    SetIcon(m_hIcon, TRUE);            // 设置大图标
    SetIcon(m_hIcon, FALSE);        // 设置小图标

    //// TODO: 在此添加额外的初始化代码

    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CShowImageInMFCDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialogEx::OnSysCommand(nID, lParam);
    }
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CShowImageInMFCDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // 用于绘制的设备上下文

        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // 使图标在工作区矩形中居中
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // 绘制图标
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialogEx::OnPaint();
    }
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CShowImageInMFCDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}


// 方法1:
void CShowImageInMFCDlg::OnBnClickedBtnReadimg()
{
    // TODO: 在此添加控件通知处理程序代码
    CFileDialog openFileDlg(TRUE,/*FileOpen*/
        _T("*.bmp"),
        NULL,
        OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY /*| OFN_ALLOWMULTISELECT 可以开启多选模式*/,
        _T("Image Files(*.bmp;*.png;*.jpg;*.raw)|*.bmp; *.png; *.jpg; *.raw|All Files (*.*)|*.*||"));
    openFileDlg.m_ofn.lpstrTitle = _T("选择图片");            // 设置对话框的标题

    if (openFileDlg.DoModal() != IDOK) {
        return;
    }
    CString filePath = openFileDlg.GetPathName();

    USES_CONVERSION;
    char *s = T2A(filePath);
    
    if (hNameWindowParent) {
        //不显示图像或销毁图像
        detachWindow("win", hNameWindowParent);
    }
    attachWindow("win", hNameWindowParent, IDC_STATIC_IMAGE);
    Mat mat = imread(s, true);
    showImage("win", IDC_STATIC_IMAGE, mat);
}

bool CShowImageInMFCDlg::attachWindow(const std::string &cvWindowName, HWND &hNameWindowParent, UINT nControlID)
{
    cv::destroyWindow(cvWindowName);
    cv::namedWindow(cvWindowName, WINDOW_AUTOSIZE);
    HWND hWnd = (HWND)cvGetWindowHandle(cvWindowName.c_str());
    hNameWindowParent = ::GetParent(hWnd);
    ::SetParent(hWnd, GetDlgItem(nControlID)->m_hWnd);
    ::ShowWindow(hNameWindowParent, SW_HIDE);
    return true;
}

bool CShowImageInMFCDlg::detachWindow(const std::string &cvWindowName, HWND hNameWindowParent)
{
    cv::destroyWindow(cvWindowName);
    if (hNameWindowParent)
    {
        ::ShowWindow(hNameWindowParent, SW_HIDE);
        ::PostMessage(hNameWindowParent, WM_CLOSE, 0, 0);
    }

    return true;
}

bool CShowImageInMFCDlg::showImage(const std::string &cvWindowName, UINT nControlID, cv::Mat mat, bool bRoomToControlSize)
{
    CRect rect;
    GetDlgItem(nControlID)->GetClientRect(&rect);
    if (bRoomToControlSize)
    {
        cv::resize(mat, mat, cv::Size(rect.Width(), rect.Height()));
    }
    imshow(cvWindowName, mat);

    return true;
}

// 方法2:
void CShowImageInMFCDlg::OnBnClickedBtnRaed2()
{
    // TODO: 在此添加控件通知处理程序代码

    CFileDialog openFileDlg(TRUE,/*FileOpen*/
        _T("*.bmp"),
        NULL,
        OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY /*| OFN_ALLOWMULTISELECT 可以开启多选模式*/,
        _T("Image Files(*.bmp;*.png;*.jpg;*.raw)|*.bmp; *.png; *.jpg; *.raw|All Files (*.*)|*.*||"));
    openFileDlg.m_ofn.lpstrTitle = _T("选择图片");            // 设置对话框的标题

    if (openFileDlg.DoModal() != IDOK) {
        return;
    }
    CString filePath = openFileDlg.GetPathName();

    USES_CONVERSION;
    char *s = T2A(filePath);
    //利用CvvImage显示图像
    IplImage *image;
    image = cvLoadImage(s);
    CvvImage cimg;
    CRect rect;
    GetDlgItem(IDC_STATIC_IMAGE)->GetClientRect(&rect);
    CDC *pDC = GetDlgItem(IDC_STATIC_IMAGE)->GetDC();
    cimg.CopyOf(image);
    cimg.DrawToHDC(pDC->GetSafeHdc(), &rect);
    ReleaseDC(pDC);
}

// 方法3:
void CShowImageInMFCDlg::OnBnClickedBtnRaed3()
{
    CFileDialog openFileDlg(TRUE,/*FileOpen*/
        _T("*.bmp"),
        NULL,
        OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY /*| OFN_ALLOWMULTISELECT 可以开启多选模式*/,
        _T("Image Files(*.bmp;*.png;*.jpg;*.raw)|*.bmp; *.png; *.jpg; *.raw|All Files (*.*)|*.*||"));
    openFileDlg.m_ofn.lpstrTitle = _T("选择图片");            // 设置对话框的标题

    if (openFileDlg.DoModal() != IDOK) {
        return;
    }
    CString filePath = openFileDlg.GetPathName();

    USES_CONVERSION;
    char *s = T2A(filePath);
    // TODO: 在此添加控件通知处理程序代码
    Mat image;
    image = imread(s);
    DrawMat(image, IDC_STATIC_IMAGE, true);
    return;
}


void CShowImageInMFCDlg::DrawMat(cv::Mat &img, UINT nControlID, bool bRoomToControlSize)
{
    cv::Mat imgTmp;
    CRect rect;
    GetDlgItem(nControlID)->GetClientRect(&rect);  // 获取控件大小
    if (bRoomToControlSize)
    {
        cv::resize(img, imgTmp, cv::Size(rect.Width(), rect.Height()));// 缩小或放大Mat并备份
    }
    else
    {
        img.copyTo(imgTmp);
    }

    switch (imgTmp.channels())
    {
    case 1:
        cv::cvtColor(imgTmp, imgTmp, CV_GRAY2BGRA); // GRAY单通道
        break;
    case 3:
        cv::cvtColor(imgTmp, imgTmp, CV_BGR2BGRA);  // BGR三通道
        break;
    default:
        break;
    }

    int pixelBytes = imgTmp.channels()*(imgTmp.depth() + 1); // 计算一个像素多少个字节
                                                             // 制作bitmapinfo(数据头)
    BITMAPINFO bitInfo;
    bitInfo.bmiHeader.biBitCount = 8 * pixelBytes;
    bitInfo.bmiHeader.biWidth = imgTmp.cols;
    bitInfo.bmiHeader.biHeight = -imgTmp.rows;
    bitInfo.bmiHeader.biPlanes = 1;
    bitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bitInfo.bmiHeader.biCompression = BI_RGB;
    bitInfo.bmiHeader.biClrImportant = 0;
    bitInfo.bmiHeader.biClrUsed = 0;
    bitInfo.bmiHeader.biSizeImage = 0;
    bitInfo.bmiHeader.biXPelsPerMeter = 0;
    bitInfo.bmiHeader.biYPelsPerMeter = 0;
    // Mat.data + bitmap数据头 -> MFC
    CDC *pDC = GetDlgItem(nControlID)->GetDC();
    pDC->SetStretchBltMode(COLORONCOLOR);
    if (bRoomToControlSize)
    {
        ::StretchDIBits(pDC->GetSafeHdc()
            , 0, 0, rect.Width(), rect.Height()
            , 0, 0, imgTmp.cols, imgTmp.rows,
            imgTmp.data, &bitInfo, DIB_RGB_COLORS, SRCCOPY);
    }
    else
    {
        int minWidth = min(imgTmp.cols, rect.Width());
        int minHeight = min(imgTmp.rows, rect.Height());
        ::StretchDIBits(
            pDC->GetSafeHdc(),
            0, 0, minWidth, minHeight,
            0, 0, minWidth, minHeight,
            imgTmp.data,
            &bitInfo,
            DIB_RGB_COLORS,
            SRCCOPY
        );
    }
    ReleaseDC(pDC);
}

CvvImage类的头文件及其实现:

 1 #pragma once
 2 
 3 #ifndef CVVIMAGE_CLASS_DEF
 4 #define CVVIMAGE_CLASS_DEF
 5 
 6 #include <opencv/cv.h>
 7 #include <opencv/highgui.h>
 8 
 9 /* CvvImage class definition */
10 class CvvImage
11 {
12 public:
13     CvvImage();
14     virtual ~CvvImage();
15 
16     /* Create image (BGR or grayscale) */
17     virtual bool Create(int width, int height, int bits_per_pixel, int image_origin = 0);
18 
19     /* Load image from specified file */
20     virtual bool Load(const char* filename, int desired_color = 1);
21 
22     /* Load rectangle from the file */
23     virtual bool LoadRect(const char* filename,
24         int desired_color, CvRect r);
25 
26 #if defined WIN32 || defined _WIN32
27     virtual bool LoadRect(const char* filename,
28         int desired_color, RECT r)
29     {
30         return LoadRect(filename, desired_color,
31             cvRect(r.left, r.top, r.right - r.left, r.bottom - r.top));
32     }
33 #endif
34 
35     /* Save entire image to specified file. */
36     virtual bool Save(const char* filename);
37 
38     /* Get copy of input image ROI */
39     virtual void CopyOf(CvvImage& image, int desired_color = -1);
40     virtual void CopyOf(IplImage* img, int desired_color = -1);
41 
42     IplImage* GetImage() { return m_img; };
43     virtual void Destroy(void);
44 
45     /* width and height of ROI */
46     int Width() { return !m_img ? 0 : !m_img->roi ? m_img->width : m_img->roi->width; };
47     int Height() { return !m_img ? 0 : !m_img->roi ? m_img->height : m_img->roi->height; };
48     int Bpp() { return m_img ? (m_img->depth & 255)*m_img->nChannels : 0; };
49 
50     virtual void Fill(int color);
51 
52     /* draw to highgui window */
53     virtual void Show(const char* window);
54 
55 #if defined WIN32 || defined _WIN32
56     /* draw part of image to the specified DC */
57     virtual void Show(HDC dc, int x, int y, int width, int height,
58         int from_x = 0, int from_y = 0);
59     /* draw the current image ROI to the specified rectangle of the destination DC */
60     virtual void DrawToHDC(HDC hDCDst, RECT* pDstRect);
61 #endif
62 
63 protected:
64 
65     IplImage* m_img;
66 };
67 
68 typedef CvvImage CImage;
69 #endif
  1 #include "stdafx.h"
  2 #include "CvvImage.h"
  3 
  4 //
  5 // Construction/Destruction
  6 //
  7 
  8 
  9 CV_INLINE RECT NormalizeRect(RECT r);
 10 CV_INLINE RECT NormalizeRect(RECT r)
 11 {
 12     int t;
 13 
 14 
 15     if (r.left > r.right)
 16     {
 17         t = r.left;
 18         r.left = r.right;
 19         r.right = t;
 20     }
 21 
 22 
 23     if (r.top > r.bottom)
 24     {
 25         t = r.top;
 26         r.top = r.bottom;
 27         r.bottom = t;
 28     }
 29 
 30 
 31     return r;
 32 }
 33 
 34 
 35 CV_INLINE CvRect RectToCvRect(RECT sr);
 36 CV_INLINE CvRect RectToCvRect(RECT sr)
 37 {
 38     sr = NormalizeRect(sr);
 39     return cvRect(sr.left, sr.top, sr.right - sr.left, sr.bottom - sr.top);
 40 }
 41 
 42 
 43 CV_INLINE RECT CvRectToRect(CvRect sr);
 44 CV_INLINE RECT CvRectToRect(CvRect sr)
 45 {
 46     RECT dr;
 47     dr.left = sr.x;
 48     dr.top = sr.y;
 49     dr.right = sr.x + sr.width;
 50     dr.bottom = sr.y + sr.height;
 51     return dr;
 52 }
 53 
 54 
 55 CV_INLINE IplROI RectToROI(RECT r);
 56 CV_INLINE IplROI RectToROI(RECT r)
 57 {
 58     IplROI roi;
 59     r = NormalizeRect(r);
 60     roi.xOffset = r.left;
 61     roi.yOffset = r.top;
 62     roi.width = r.right - r.left;
 63     roi.height = r.bottom - r.top;
 64     roi.coi = 0;
 65     return roi;
 66 }
 67 
 68 
 69 void FillBitmapInfo(BITMAPINFO* bmi, int width, int height, int bpp, int origin)
 70 {
 71     assert(bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32));
 72 
 73     BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);
 74     memset(bmih, 0, sizeof(*bmih));
 75     bmih->biSize = sizeof(BITMAPINFOHEADER);
 76     bmih->biWidth = width;
 77     bmih->biHeight = origin ? abs(height) : -abs(height);
 78     bmih->biPlanes = 1;
 79     bmih->biBitCount = (unsigned short)bpp;
 80     bmih->biCompression = BI_RGB;
 81 
 82 
 83     if (bpp == 8)
 84     {
 85         RGBQUAD* palette = bmi->bmiColors;
 86         int i;
 87         for (i = 0; i < 256; i++)
 88         {
 89             palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
 90             palette[i].rgbReserved = 0;
 91         }
 92     }
 93 }
 94 
 95 
 96 CvvImage::CvvImage()
 97 {
 98     m_img = 0;
 99 }
100 
101 
102 void CvvImage::Destroy()
103 {
104     cvReleaseImage(&m_img);
105 }
106 
107 
108 CvvImage::~CvvImage()
109 {
110     Destroy();
111 }
112 
113 
114 bool CvvImage::Create(int w, int h, int bpp, int origin)
115 {
116     const unsigned max_img_size = 10000;
117 
118 
119     if ((bpp != 8 && bpp != 24 && bpp != 32) ||
120         (unsigned)w >= max_img_size || (unsigned)h >= max_img_size ||
121         (origin != IPL_ORIGIN_TL && origin != IPL_ORIGIN_BL))
122     {
123         assert(0); // most probably, it is a programming error
124         return false;
125     }
126 
127 
128     if (!m_img || Bpp() != bpp || m_img->width != w || m_img->height != h)
129     {
130         if (m_img && m_img->nSize == sizeof(IplImage))
131             Destroy();
132 
133 
134         /* prepare IPL header */
135         m_img = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, bpp / 8);
136     }
137 
138 
139     if (m_img)
140         m_img->origin = origin == 0 ? IPL_ORIGIN_TL : IPL_ORIGIN_BL;
141 
142 
143     return m_img != 0;
144 }
145 
146 
147 void CvvImage::CopyOf(CvvImage& image, int desired_color)
148 {
149     IplImage* img = image.GetImage();
150     if (img)
151     {
152         CopyOf(img, desired_color);
153     }
154 }
155 
156 
157 #define HG_IS_IMAGE(img) 
158     ((img) != 0 && ((const IplImage*)(img))->nSize == sizeof(IplImage) && 
159     ((IplImage*)img)->imageData != 0)
160 
161 
162 void CvvImage::CopyOf(IplImage* img, int desired_color)
163 {
164     if (HG_IS_IMAGE(img))
165     {
166         int color = desired_color;
167         //CvSize size = cvGetSize(img);//opencv3.4.4中调用cvGetSize出错,使用以下语句替换
168         CvSize size;
169         size.width = img->width;
170         size.height = img->height;
171 
172         if (color < 0)
173             color = img->nChannels > 1;
174 
175         if (Create(size.width, size.height,
176             (!color ? 1 : img->nChannels > 1 ? img->nChannels : 3) * 8,
177             img->origin))
178         {
179             cvConvertImage(img, m_img, 0);
180         }
181     }
182 }
183 
184 
185 bool CvvImage::Load(const char* filename, int desired_color)
186 {
187     IplImage* img = cvLoadImage(filename, desired_color);
188     if (!img)
189         return false;
190 
191     CopyOf(img, desired_color);
192     cvReleaseImage(&img);
193     return true;
194 }
195 
196 
197 bool CvvImage::LoadRect(const char* filename,
198     int desired_color, CvRect r)
199 {
200     if (r.width < 0 || r.height < 0) return false;
201 
202 
203     IplImage* img = cvLoadImage(filename, desired_color);
204     if (!img)
205         return false;
206 
207 
208     if (r.width == 0 || r.height == 0)
209     {
210         r.width = img->width;
211         r.height = img->height;
212         r.x = r.y = 0;
213     }
214 
215 
216     if (r.x > img->width || r.y > img->height ||
217         r.x + r.width < 0 || r.y + r.height < 0)
218     {
219         cvReleaseImage(&img);
220         return false;
221     }
222 
223 
224     /* truncate r to source image */
225     if (r.x < 0)
226     {
227         r.width += r.x;
228         r.x = 0;
229     }
230     if (r.y < 0)
231     {
232         r.height += r.y;
233         r.y = 0;
234     }
235 
236 
237     if (r.x + r.width > img->width)
238         r.width = img->width - r.x;
239 
240 
241     if (r.y + r.height > img->height)
242         r.height = img->height - r.y;
243 
244 
245     cvSetImageROI(img, r);
246     CopyOf(img, desired_color);
247 
248 
249     cvReleaseImage(&img);
250     return true;
251 }
252 
253 
254 bool CvvImage::Save(const char* filename)
255 {
256     if (!m_img)
257         return false;
258     cvSaveImage(filename, m_img);
259     return true;
260 }
261 
262 
263 void CvvImage::Show(const char* window)
264 {
265     if (m_img)
266         cvShowImage(window, m_img);
267 }
268 
269 
270 void CvvImage::Show(HDC dc, int x, int y, int w, int h, int from_x, int from_y)
271 {
272     if (m_img && m_img->depth == IPL_DEPTH_8U)
273     {
274         uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];
275         BITMAPINFO* bmi = (BITMAPINFO*)buffer;
276         int bmp_w = m_img->width, bmp_h = m_img->height;
277         FillBitmapInfo(bmi, bmp_w, bmp_h, Bpp(), m_img->origin);
278         from_x = MIN(MAX(from_x, 0), bmp_w - 1);
279         from_y = MIN(MAX(from_y, 0), bmp_h - 1);
280         int sw = MAX(MIN(bmp_w - from_x, w), 0);
281         int sh = MAX(MIN(bmp_h - from_y, h), 0);
282         SetDIBitsToDevice(
283             dc, x, y, sw, sh, from_x, from_y, from_y, sh,
284             m_img->imageData + from_y*m_img->widthStep,
285             bmi, DIB_RGB_COLORS);
286     }
287 }
288 
289 
290 void CvvImage::DrawToHDC(HDC hDCDst, RECT* pDstRect)
291 {
292     if (pDstRect && m_img && m_img->depth == IPL_DEPTH_8U && m_img->imageData)
293     {
294         uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];
295         BITMAPINFO* bmi = (BITMAPINFO*)buffer;
296         int bmp_w = m_img->width, bmp_h = m_img->height;
297 
298         CvRect roi = cvGetImageROI(m_img);
299         CvRect dst = RectToCvRect(*pDstRect);
300         if (roi.width == dst.width && roi.height == dst.height)
301         {
302             Show(hDCDst, dst.x, dst.y, dst.width, dst.height, roi.x, roi.y);
303             return;
304         }
305 
306         if (roi.width > dst.width)
307         {
308             SetStretchBltMode(
309                 hDCDst, // handle to device context
310                 HALFTONE);
311         }
312         else
313         {
314             SetStretchBltMode(
315                 hDCDst, // handle to device context
316                 COLORONCOLOR);
317         }
318 
319         FillBitmapInfo(bmi, bmp_w, bmp_h, Bpp(), m_img->origin);
320 
321         ::StretchDIBits(
322             hDCDst,
323             dst.x, dst.y, dst.width, dst.height,
324             roi.x, roi.y, roi.width, roi.height,
325             m_img->imageData, bmi, DIB_RGB_COLORS, SRCCOPY);
326     }
327 }
328 
329 
330 void CvvImage::Fill(int color)
331 {
332     cvSet(m_img, cvScalar(color & 255, (color >> 8) & 255, (color >> 16) & 255, (color >> 24) & 255));
333 }

效果图:

MFC中使用Picture Control控件显示OpenCV图像几种方法第1张

免责声明:文章转载自《MFC中使用Picture Control控件显示OpenCV图像几种方法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Revit 二次开发 元素创建与修改练习faker生成随机数据下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

网络编程学习小结

几种网络编程方式: ISAPI、CGI、WinInet、Winsock 它们之间的差别: 1) ISAPI主要是开发基于浏览器client与server端程序。效率比CGI方式高,并且也扩展了CGI没有的一些功能。(基于TCP/IP模型中的应用层) 2) CGI主要是开发基于浏览器client与server端程序。(基于TCP/IP模型中的应用层...

高效的数据压缩编码方式 Protobuf

一. protocol buffers 是什么? Protocol buffers 是一种语言中立,平台无关,可扩展的序列化数据的格式,可用于通信协议,数据存储等。 Protocol buffers 在序列化数据方面,它是灵活的,高效的。相比于 XML 来说,Protocol buffers 更加小巧,更加快速,更加简单。一旦定义了要处理的数据的数据结构之...

JSONCkecker(C语言版本)

/* JSON_checker.h */ typedef struct JSON_checker_struct { int valid; int state; int depth; int top; int* stack; } * JSON_checker; extern JSON_che...

vue 调用本地json配置

在webpack.dev.conf.js文件中 /*----------------jsonServer---------*/ /*引入json-server*/const jsonServer = require('json-server') /*搭建一个server*/const apiServer =jsonServer.create() /*将d...

【转】MFC 无边框窗口的拖动

MFC中无边框窗口的拖动 void CXXXXDialog::OnLButtonDown(UINT nFlags, CPoint point) { PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y)); }...

Unicode和中午互转

import java.io.UnsupportedEncodingException; public class TestUnicode{ /* * 中文转unicode编码 */ public static String gbEncoding(final String gbString) { char[] utfBytes = gbString.to...