zoukankan      html  css  js  c++  java
  • MFC中使用Picture Control控件显示OpenCV图像几种方法

    本文参考自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 }

    效果图:

  • 相关阅读:
    党史回顾+十九大习思想+中国历史事件+地理+航天史及古代天文历法
    国际组织
    生活-常识-物理
    生物
    数量题目总结-利润排列组合
    数量题目总结-工程最值集合
    考公错题记录表
    个人向简历介绍
    数据库操作大全
    团队博客作业-技术规格说明书
  • 原文地址:https://www.cnblogs.com/djh5520/p/13786050.html
Copyright © 2011-2022 走看看