首页 > 代码库 > OpenCV:基于MFC的视频播放器和图片读取器
OpenCV:基于MFC的视频播放器和图片读取器
实例工程包下载【OpenCV:基于MFC的视频播放器和图片读取器】
一、实现的功能
1、打开本地视频进行读取、播放、暂停、停止控制
2、图片打开功能分为两种:可使用“打开图片”按钮打开本地图片,或者点击comobox里面设定的图片列表选择并显示图片
二、编译环境
OS:Win8.1 x64
IDE: Visual Studio 2013
OpenCV: 2.4.8
三、主要思路
1、视频的滑动条控制:
①主窗体的OnHScroll()响应函数负责响应slider滑动条的变化,这样就轻松搞定slider控件与拖动滑动条动作与视频播放的联动。
②新建虚拟的slider实例和slider滑动位置的全局变量,通过数据交换函数予以关系绑定
③通过OpenCV的函数cvSetCaptureProperty()和slider滑动位置全局变量来确定指向视频的哪个帧位置,并进行加载显示到Picture控件中
2、combobox中图片的对应显示:①addstring()向列表中添加选项
②将图片名字改为列表中的选项名
③根据选项名通过cvloadImage()打开图片
四、核心代码
<span style="font-family:Microsoft YaHei;">// VideoPlayerDlg.cpp : 实现文件 // #include "stdafx.h" #include "VideoPlayer.h" #include "VideoPlayerDlg.h" #include "CvvImage.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialog { public: CAboutDlg(); // 对话框数据 enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() // CVideoPlayerDlg 对话框 CVideoPlayerDlg::CVideoPlayerDlg(CWnd* pParent /*=NULL*/) : CDialog(CVideoPlayerDlg::IDD, pParent) , IsPlaying(false) , IsAviFile(false) , g_VideoPath(_T("")) , pDC(NULL) , pwnd(NULL) , b_flagProcess(false) , g_m_int(0) , g_pCapture(NULL) , g_pFrame(NULL) , g_m_run(0) , TheImage(NULL) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CVideoPlayerDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_SLIDER1, m_slider); DDX_Control(pDX, IDC_COMBO4, m_cbExample); } BEGIN_MESSAGE_MAP(CVideoPlayerDlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_BN_CLICKED(IDC_Open, &CVideoPlayerDlg::OnBnClickedOpen) ON_BN_CLICKED(IDC_Stop, &CVideoPlayerDlg::OnBnClickedStop) ON_WM_HSCROLL() ON_BN_CLICKED(IDC_Play, &CVideoPlayerDlg::OnBnClickedPlay) ON_BN_CLICKED(IDOK, &CVideoPlayerDlg::OnBnClickedOk) ON_BN_CLICKED(IDCANCEL, &CVideoPlayerDlg::OnBnClickedCancel) ON_BN_CLICKED(IDC_Pause, &CVideoPlayerDlg::OnBnClickedPause) ON_STN_CLICKED(IDC_SHOWPIC, &CVideoPlayerDlg::OnStnClickedShowpic) ON_BN_CLICKED(IDC_img_open, &CVideoPlayerDlg::OnBnClickedReadimg) ON_EN_CHANGE(IDC_EDIT_FRAME_show, &CVideoPlayerDlg::OnEnChangeEditFrameshow) ON_CBN_SELCHANGE(IDC_COMBO4, &CVideoPlayerDlg::OnCbnSelchangeCombo4) END_MESSAGE_MAP() // CVideoPlayerDlg 消息处理程序 BOOL CVideoPlayerDlg::OnInitDialog() { CDialog::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 CvSize ImgSize; ImgSize.height = IMAGE_HEIGHT; ImgSize.width = IMAGE_WIDTH; TheImage = cvCreateImage(ImgSize, IPL_DEPTH_8U, IMAGE_CHANNELS); 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: 在此添加额外的初始化代码 GetDlgItem( IDC_Play )->EnableWindow( FALSE ); GetDlgItem( IDC_Pause )->EnableWindow( FALSE ); GetDlgItem( IDC_Stop )->EnableWindow( FALSE ); GetDlgItem( IDC_SLIDER1 )->EnableWindow( FALSE ); m_cbExample.AddString("photos/1.bmp"); //combobox里面的图片保存在photos文件夹内 m_cbExample.AddString("photos/2.bmp"); m_cbExample.AddString("photos/3.bmp"); m_cbExample.AddString("photos/4.bmp"); m_cbExample.AddString("photos/5.bmp"); m_cbExample.AddString("photos/6.bmp"); m_cbExample.AddString("photos/7.bmp"); m_cbExample.AddString("photos/8.bmp"); m_cbExample.AddString("photos/9.bmp"); m_cbExample.AddString("photos/10.bmp"); pwnd = GetDlgItem(IDC_SHOWPIC); pwnd->MoveWindow(40,40,352,288); pDC =pwnd->GetDC(); hDC= pDC->GetSafeHdc(); pwnd->GetClientRect(&rect); Invalidate(); m_slider.SetRange(0,100); m_slider.SetTicFreq(10); ImgSize.height = IMAGE_HEIGHT; ImgSize.width = IMAGE_WIDTH; g_pFrame = cvCreateImage( ImgSize, IPL_DEPTH_8U, IMAGE_CHANNELS ); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } void CVideoPlayerDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CVideoPlayerDlg::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 { CDialog::OnPaint(); CDialog::UpdateWindow(); // 更新windows窗口,如果无这步调用,图片显示还会出现问题 ShowImage(TheImage, IDC_ShowImg); // 重绘图片函数 } if(!g_m_run) { CDC MemDC; MemDC.CreateCompatibleDC(NULL); pDC->StretchBlt(rect.left,rect.top,rect.Width(),rect.Height(),&MemDC,0,0,48,48,SRCCOPY); MemDC.DeleteDC(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSOR CVideoPlayerDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CVideoPlayerDlg::OnBnClickedOpen() { // TODO: 在此添加控件通知处理程序代码 CFileDialog dlg( TRUE, _T("*.avi"), NULL, OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, _T("*.avi|*.avi|*.rmvb|*.rmvb|*.mp4|*.mp4|*.wmv|*.wmv| All Files (*.*) |*.*||"), NULL ); dlg.m_ofn.lpstrTitle = _T("选取视频文件"); if( dlg.DoModal() != IDOK ) return; g_VideoPath = dlg.GetPathName(); GetDlgItem( IDC_Play )->EnableWindow( TRUE ); GetDlgItem( IDC_Pause )->EnableWindow( TRUE ); GetDlgItem( IDC_Stop )->EnableWindow( TRUE ); GetDlgItem( IDC_SLIDER1 )->EnableWindow( TRUE ); } void CVideoPlayerDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { // TODO: 在此添加消息处理程序代码和/或调用默认值 CSliderCtrl *pSlidCtrl=(CSliderCtrl*)GetDlgItem(IDC_SLIDER1); g_m_int=pSlidCtrl->GetPos(); char chEdit[10]; itoa(g_m_int,chEdit,10); SetDlgItemText(IDC_EDIT_FRAME_show,chEdit); if(g_pCapture) { cvSetCaptureProperty(g_pCapture,CV_CAP_PROP_POS_FRAMES,g_m_int); } CDialog::OnHScroll(nSBCode, nPos, pScrollBar); } void CVideoPlayerDlg::OnBnClickedPlay() { // TODO: 在此添加控件通知处理程序代码 if( g_VideoPath == "" ) { MessageBox("请先选择视频文件!"); return; } else { if(!(g_pCapture = cvCreateFileCapture( g_VideoPath ))) { MessageBox("打开视频文件失败!"); return; } } int frames = (int) cvGetCaptureProperty( g_pCapture, CV_CAP_PROP_FRAME_COUNT ); m_slider.SetRange(0,frames-1); m_slider.SetTicFreq(1); char chEdit[10]; itoa(frames,chEdit,10); SetDlgItemText(IDC_EDIT_FRAME_count,chEdit); GetDlgItem( IDC_Open )->EnableWindow( FALSE ); GetDlgItem( IDC_Play )->EnableWindow( FALSE ); GetDlgItem( IDC_Pause )->EnableWindow( TRUE ); GetDlgItem( IDC_Stop )->EnableWindow( TRUE ); IplImage *pFrame = NULL; cvNamedWindow("video"); cvResizeWindow("video",1,1); HWND hWnd = (HWND) cvGetWindowHandle("video"); HWND hParent = ::GetParent(hWnd); HWND hwnd1=::FindWindow("CVideoPlayerDlg","VideoPlayer"); ::SetParent(hWnd, hwnd1); ::ShowWindow(hParent, SW_HIDE); if( g_pFrame ) cvZero( g_pFrame ); g_m_run = 1; if(g_pCapture) { cvSetCaptureProperty(g_pCapture,CV_CAP_PROP_POS_FRAMES,g_m_int); } while( (g_m_int < frames) & (g_m_run == 1) ) { pFrame = cvQueryFrame( g_pCapture ); IplImage* newframe = cvCloneImage(pFrame); ResizeImage( newframe ); ShowImage( g_pFrame , IDC_SHOWPIC); if (cvWaitKey(20) == 27) break; m_slider.SetPos(g_m_int); char chEdit[10]; //g_m_int=numfrm; itoa(g_m_int,chEdit,10); SetDlgItemText(IDC_EDIT_FRAME_show,chEdit); //numfrm++; g_m_int++; cvReleaseImage( &newframe ); } if(g_m_int==frames) { g_m_int=0; m_slider.SetPos(g_m_int); g_m_run = 0; if( g_pFrame ) { cvZero( g_pFrame ); ShowImage( g_pFrame , IDC_SHOWPIC ); } GetDlgItem( IDC_Open )->EnableWindow( TRUE ); GetDlgItem( IDC_Play )->EnableWindow( TRUE ); GetDlgItem( IDC_Pause )->EnableWindow( FALSE ); GetDlgItem( IDC_Stop )->EnableWindow( FALSE ); } cvReleaseCapture(&g_pCapture); cvDestroyWindow("video"); } void CVideoPlayerDlg::OnBnClickedStop() { // TODO: 在此添加控件通知处理程序代码 CDC MemDC; MemDC.CreateCompatibleDC(NULL); pDC->StretchBlt(rect.left,rect.top,rect.Width(),rect.Height(),&MemDC,0,0,48,48,SRCCOPY); MemDC.DeleteDC(); GetDlgItem( IDC_Open )->EnableWindow( TRUE ); GetDlgItem( IDC_Play )->EnableWindow( TRUE ); GetDlgItem( IDC_Pause )->EnableWindow( FALSE ); GetDlgItem( IDC_Stop )->EnableWindow( FALSE ); g_m_run=0; g_m_int=0; m_slider.SetPos(g_m_int); char chEdit[10]; itoa(g_m_int,chEdit,10); SetDlgItemText(IDC_EDIT_FRAME_show,chEdit); return; } void CVideoPlayerDlg::ResizeImage(IplImage* img) { int w = img->width; int h = img->height; int max = (w > h)? w: h; float scale = (float) ( (float) max / 256.0f ); int nw = (int)( w/scale ); int nh = (int)( h/scale ); int tlx = (nw > nh)? 0: (int)(256-nw)/2; int tly = (nw > nh)? (int)(256-nh)/2: 0; cvSetImageROI( g_pFrame, cvRect( tlx, tly, nw, nh) ); cvResize( img, g_pFrame ); cvResetImageROI( g_pFrame ); } void CVideoPlayerDlg::ShowImage(IplImage* img, UINT ID) { CDC* pDC = GetDlgItem( ID ) ->GetDC(); HDC hDC = pDC ->GetSafeHdc(); CRect rect; GetDlgItem(ID) ->GetClientRect( &rect ); int rw = rect.right - rect.left; int rh = rect.bottom - rect.top; int iw = img->width; int ih = img->height; int tx = (int)(rw - iw)/2; int ty = (int)(rh - ih)/2; SetRect( rect, tx, ty, tx+iw, ty+ih ); CvvImage cimg; cimg.CopyOf( img ); cimg.DrawToHDC( hDC, &rect ); ReleaseDC( pDC ); } void CVideoPlayerDlg::OnBnClickedOk() { // TODO: 在此添加控件通知处理程序代码 g_m_run = 0; cvReleaseImage( &g_pFrame ); cvDestroyAllWindows(); OnOK(); } void CVideoPlayerDlg::OnBnClickedCancel() { // TODO: 在此添加控件通知处理程序代码 g_m_run = 0; cvReleaseImage( &g_pFrame ); cvDestroyAllWindows(); OnCancel(); } void CVideoPlayerDlg::OnBnClickedPause() { // TODO: 在此添加控件通知处理程序代码 g_m_run=0; GetDlgItem( IDC_Open )->EnableWindow( FALSE ); GetDlgItem( IDC_Play )->EnableWindow( TRUE ); GetDlgItem( IDC_Pause )->EnableWindow( FALSE ); GetDlgItem( IDC_Stop )->EnableWindow( FALSE ); } void CVideoPlayerDlg::OnStnClickedShowpic() { // TODO: 在此添加控件通知处理程序代码 } void CVideoPlayerDlg::OnBnClickedReadimg() { // TODO: 在此添加控件通知处理程序代码 CFileDialog dlg( TRUE, _T("*.bmp"), NULL, OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, _T("image files (*.bmp; *.jpg) |*.bmp; *.jpg | All Files (*.*) |*.*||"), NULL ); // 选项图片的约定 dlg.m_ofn.lpstrTitle = _T("Open Image"); // 打开文件对话框的标题名 if (dlg.DoModal() != IDOK) // 判断是否获得图片 return; CString mPath = dlg.GetPathName(); // 获取图片路径 IplImage* ipl = cvLoadImage(mPath, 1); // 读取图片、缓存到一个局部变量 ipl 中 if (!ipl) // 判断是否成功载入图片 return; if (TheImage) // 对上一幅显示的图片数据清零 cvZero(TheImage); resize_image(ipl); // 对读入的图片进行缩放,使其宽或高最大值者刚好等于 256,再复制到 TheImage 中 show_image(TheImage, IDC_ShowImg); // 调用显示图片函数 cvReleaseImage(&ipl); // 释放 ipl 占用的内存 } void CVideoPlayerDlg::show_image(IplImage* img, UINT ID) { CDC* pDC = GetDlgItem(ID)->GetDC(); // 获得显示控件的 DC HDC hDC = pDC->GetSafeHdc(); // 获取 HDC(设备句柄) 来进行绘图操作 CRect rect; GetDlgItem(ID)->GetClientRect(&rect); int rw = rect.right - rect.left; // 求出图片控件的宽和高 int rh = rect.bottom - rect.top; int iw = img->width; // 读取图片的宽和高 int ih = img->height; int tx = (int)(rw - iw) / 2; // 使图片的显示位置正好在控件的正中 int ty = (int)(rh - ih) / 2; SetRect(rect, tx, ty, tx + iw, ty + ih); CvvImage cimg; cimg.CopyOf(img); // 复制图片 cimg.DrawToHDC(hDC, &rect); // 将图片绘制到显示控件的指定区域内 ReleaseDC(pDC); } void CVideoPlayerDlg::resize_image(IplImage* img) { // 读取图片的宽和高 int w = img->width; int h = img->height; // 找出宽和高中的较大值者 int max = (w > h) ? w : h; // 计算将图片缩放到TheImage区域所需的比例因子 float scale = (float)((float)max / 256.0f); // 缩放后图片的宽和高 int nw = (int)(w / scale); int nh = (int)(h / scale); // 为了将缩放后的图片存入 TheImage 的正中部位,需计算图片在 TheImage 左上角的期望坐标值 int tlx = (nw > nh) ? 0 : (int)(256 - nw) / 2; int tly = (nw > nh) ? (int)(256 - nh) / 2 : 0; // 设置 TheImage 的 ROI 区域,用来存入图片 img cvSetImageROI(TheImage, cvRect(tlx, tly, nw, nh)); // 对图片 img 进行缩放,并存入到 TheImage 中 cvResize(img, TheImage); // 重置 TheImage 的 ROI 准备读入下一幅图片 cvResetImageROI(TheImage); } void CVideoPlayerDlg::OnEnChangeEditFrameshow() { // TODO: 如果该控件是 RICHEDIT 控件,它将不 // 发送此通知,除非重写 CDialog::OnInitDialog() // 函数并调用 CRichEditCtrl().SetEventMask(), // 同时将 ENM_CHANGE 标志“或”运算到掩码中。 // TODO: 在此添加控件通知处理程序代码 } void CVideoPlayerDlg::OnCbnSelchangeCombo4() { int nIndex = m_cbExample.GetCurSel(); CString strCBText; m_cbExample.GetLBText(nIndex, strCBText); IplImage* ipl = cvLoadImage(strCBText, 1); // 读取图片、缓存到一个局部变量 ipl 中 if (!ipl) // 判断是否成功载入图片 return; if (TheImage) // 对上一幅显示的图片数据清零 cvZero(TheImage); resize_image(ipl); // 对读入的图片进行缩放,使其宽或高最大值者刚好等于 256,再复制到 TheImage 中 show_image(TheImage, IDC_ShowImg); // 调用显示图片函数 cvReleaseImage(&ipl); // 释放 ipl 占用的内存 // TODO: 在此添加控件通知处理程序代码 } </span>五、相关问题的解决
1、OpenCV2.4.8找不到CImage(CvvImage)的解决办法:为了不和MFC中的CImage冲突,我们重新将CvvImage定义为CvImage。
在需要的地方引入 #include "CvvImage.h" 就可以用了。
<span style="font-family:Microsoft YaHei;">为了不和MFC中的CImage冲突,我们重新将CvvImage定义为CvImage。 在需要的地方引入 #include "CvvImage.h" 就可以用了。 //================================================================ // CvvImage.h //================================================================ #pragma once #ifndef CVVIMAGE_CLASS_DEF #define CVVIMAGE_CLASS_DEF #include "opencv2/highgui/highgui.hpp" #include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/imgproc/imgproc_c.h" class CvvImage { public: CvvImage(); virtual ~CvvImage(); virtual bool Create( int width, int height, int bits_per_pixel, int image_origin = 0 ); virtual bool Load( const char* filename, int desired_color = 1 ); virtual bool LoadRect( const char* filename, int desired_color, CvRect r ); #if defined WIN32 || defined _WIN32 virtual bool LoadRect( const char* filename, int desired_color, RECT r ) { return LoadRect( filename, desired_color, cvRect( r.left, r.top, r.right - r.left, r.bottom - r.top )); } #endif virtual bool Save( const char* filename ); virtual void CopyOf( CvvImage& image, int desired_color = -1 ); virtual void CopyOf( IplImage* img, int desired_color = -1 ); IplImage* GetImage() { return m_img; }; virtual void Destroy(void); int Width() { return !m_img ? 0 : !m_img->roi ? m_img->width : m_img->roi->width; }; int Height() { return !m_img ? 0 : !m_img->roi ? m_img->height : m_img->roi->height;}; int Bpp() { return m_img ? (m_img->depth & 255)*m_img->nChannels : 0; }; virtual void Fill( int color ); virtual void Show( const char* window ); #if defined WIN32 || defined _WIN32 virtual void Show( HDC dc, int x, int y, int width, int height, int from_x = 0, int from_y = 0 ); virtual void DrawToHDC( HDC hDCDst, RECT* pDstRect ); #endif protected: IplImage* m_img; }; typedef CvvImage CvImage; #endif //================================================================ // CvvImage.cpp //================================================================ #include "StdAfx.h" #include "CvvImage.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CV_INLINE RECT NormalizeRect( RECT r ); CV_INLINE RECT NormalizeRect( RECT r ) { int t; if( r.left > r.right ) { t = r.left; r.left = r.right; r.right = t; } if( r.top > r.bottom ) { t = r.top; r.top = r.bottom; r.bottom = t; } return r; } CV_INLINE CvRect RectToCvRect( RECT sr ); CV_INLINE CvRect RectToCvRect( RECT sr ) { sr = NormalizeRect( sr ); return cvRect( sr.left, sr.top, sr.right - sr.left, sr.bottom - sr.top ); } CV_INLINE RECT CvRectToRect( CvRect sr ); CV_INLINE RECT CvRectToRect( CvRect sr ) { RECT dr; dr.left = sr.x; dr.top = sr.y; dr.right = sr.x + sr.width; dr.bottom = sr.y + sr.height; return dr; } CV_INLINE IplROI RectToROI( RECT r ); CV_INLINE IplROI RectToROI( RECT r ) { IplROI roi; r = NormalizeRect( r ); roi.xOffset = r.left; roi.yOffset = r.top; roi.width = r.right - r.left; roi.height = r.bottom - r.top; roi.coi = 0; return roi; } void 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; } } } CvvImage::CvvImage() { m_img = 0; } void CvvImage::Destroy() { cvReleaseImage( &m_img ); } CvvImage::~CvvImage() { Destroy(); } bool CvvImage::Create( int w, int h, int bpp, int origin ) { const unsigned max_img_size = 10000; if( (bpp != 8 && bpp != 24 && bpp != 32) || (unsigned)w >= max_img_size || (unsigned)h >= max_img_size || (origin != IPL_ORIGIN_TL && origin != IPL_ORIGIN_BL)) { assert(0); // most probably, it is a programming error return false; } if( !m_img || Bpp() != bpp || m_img->width != w || m_img->height != h ) { if( m_img && m_img->nSize == sizeof(IplImage)) Destroy(); m_img = cvCreateImage( cvSize( w, h ), IPL_DEPTH_8U, bpp/8 ); } if( m_img ) m_img->origin = origin == 0 ? IPL_ORIGIN_TL : IPL_ORIGIN_BL; return m_img != 0; } void CvvImage::CopyOf( CvvImage& image, int desired_color ) { IplImage* img = image.GetImage(); if( img ) { CopyOf( img, desired_color ); } } #define HG_IS_IMAGE(img) ((img) != 0 && ((const IplImage*)(img))->nSize == sizeof(IplImage) && ((IplImage*)img)->imageData != 0) void CvvImage::CopyOf( IplImage* img, int desired_color ) { if( HG_IS_IMAGE(img) ) { int color = desired_color; CvSize size = cvGetSize( img ); if( color < 0 ) color = img->nChannels > 1; if( Create( size.width, size.height, (!color ? 1 : img->nChannels > 1 ? img->nChannels : 3)*8, img->origin )) { cvConvertImage( img, m_img, 0 ); } } } bool CvvImage::Load( const char* filename, int desired_color ) { IplImage* img = cvLoadImage( filename, desired_color ); if( !img ) return false; CopyOf( img, desired_color ); cvReleaseImage( &img ); return true; } bool CvvImage::LoadRect( const char* filename, int desired_color, CvRect r ) { if( r.width < 0 || r.height < 0 ) return false; IplImage* img = cvLoadImage( filename, desired_color ); if( !img ) return false; if( r.width == 0 || r.height == 0 ) { r.width = img->width; r.height = img->height; r.x = r.y = 0; } if( r.x > img->width || r.y > img->height || r.x + r.width < 0 || r.y + r.height < 0 ) { cvReleaseImage( &img ); return false; } if( r.x < 0 ) { r.width += r.x; r.x = 0; } if( r.y < 0 ) { r.height += r.y; r.y = 0; } if( r.x + r.width > img->width ) r.width = img->width - r.x; if( r.y + r.height > img->height ) r.height = img->height - r.y; cvSetImageROI( img, r ); CopyOf( img, desired_color ); cvReleaseImage( &img ); return true; } bool CvvImage::Save( const char* filename ) { if( !m_img ) return false; cvSaveImage( filename, m_img ); return true; } void CvvImage::Show( const char* window ) { if( m_img ) cvShowImage( window, m_img ); } void CvvImage::Show( HDC dc, int x, int y, int w, int h, int from_x, int from_y ) { if( m_img && m_img->depth == IPL_DEPTH_8U ) { uchar buffer[sizeof(BITMAPINFOHEADER) + 1024]; BITMAPINFO* bmi = (BITMAPINFO*)buffer; int bmp_w = m_img->width, bmp_h = m_img->height; FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin ); from_x = MIN( MAX( from_x, 0 ), bmp_w - 1 ); from_y = MIN( MAX( from_y, 0 ), bmp_h - 1 ); int sw = MAX( MIN( bmp_w - from_x, w ), 0 ); int sh = MAX( MIN( bmp_h - from_y, h ), 0 ); SetDIBitsToDevice( dc, x, y, sw, sh, from_x, from_y, from_y, sh, m_img->imageData + from_y*m_img->widthStep, bmi, DIB_RGB_COLORS ); } } void CvvImage::DrawToHDC( HDC hDCDst, RECT* pDstRect ) { if( pDstRect && m_img && m_img->depth == IPL_DEPTH_8U && m_img->imageData ) { uchar buffer[sizeof(BITMAPINFOHEADER) + 1024]; BITMAPINFO* bmi = (BITMAPINFO*)buffer; int bmp_w = m_img->width, bmp_h = m_img->height; CvRect roi = cvGetImageROI( m_img ); CvRect dst = RectToCvRect( *pDstRect ); if( roi.width == dst.width && roi.height == dst.height ) { Show( hDCDst, dst.x, dst.y, dst.width, dst.height, roi.x, roi.y ); return; } if( roi.width > dst.width ) { SetStretchBltMode( hDCDst, // handle to device context HALFTONE ); } else { SetStretchBltMode( hDCDst, // handle to device context COLORONCOLOR ); } FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin ); ::StretchDIBits( hDCDst, dst.x, dst.y, dst.width, dst.height, roi.x, roi.y, roi.width, roi.height, m_img->imageData, bmi, DIB_RGB_COLORS, SRCCOPY ); } } void CvvImage::Fill( int color ) { cvSet( m_img, cvScalar(color&255,(color>>8)&255,(color>>16)&255,(color>>24)&255) ); }</span>
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。