问题:
经常需要为某个算法做一个demo的时候,会经常使用Windows的MFC程序框架进行简单快速的开发,
也因此经常需要涉及到MFC上Picture Control上实时显示视频源的图片。
代码:
//
// MFC上Picture Control控件显示图像
// src 待显示的图像 (OpenCV库Mat对象结构)
// hwnd MFC显示图像的窗口句柄
//
void ShowImage (Mat& src, HWND hwnd) {
//
HDC hdc = ::GetDC (hwnd);
//
RECT rect;
::GetWindowRect (hwnd, &rect);
//
int dst_width = rect.right - rect.left;
int dst_height = rect.bottom - rect.top;
Mat image = Mat::zeros (dst_height, dst_width, src.type());
//
resize (src, image, Size (dst_width, dst_height));
int depth = image.depth();
int channel = image.channels();
int type = image.type();
CV_8U;
IPL_DEPTH_8U;
int bpp = 8 * image.channels();// 24;//8;//32;//
uchar buffer[sizeof (BITMAPINFOHEADER) + 1024];
BITMAPINFO* bmi = (BITMAPINFO*) buffer;
BITMAPINFOHEADER* bmih = & (bmi->bmiHeader);
memset (bmih, 0, sizeof (*bmih));
bmih->biSize = sizeof (BITMAPINFOHEADER);
bmih->biWidth = image.cols;
bmih->biHeight = -image.rows;
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;
}
}
//
CvRect dst (rect.left, rect.top,
rect.right - rect.left,
rect.bottom - rect.top);
::StretchDIBits (
hdc,
0, 0, dst.width, dst.height,
0, 0, image.cols, image.rows,
image.data, bmi, DIB_RGB_COLORS, SRCCOPY);
//
::ReleaseDC (hwnd, hdc);
}
// Mylaf
测试及效果:
// 获取显示控件的窗口句柄
HWND hwnd = GetDlgItem (IDC_PIC_LEFT)->GetSafeHwnd();
// 获取显示的图像
Mat img = imread ("D:\\Mylaf\\Project\\VS2013\\XMRK\\testOpenCV320\\ambush_5_left.jpg");
// 调用显示函数
ShowImage (img, hwnd);
扩展代码:
头文件:
// header file
// mylaf
struct StDisplayWnd {
HWND hwnd;
HDC hdc;
RECT rect;
BITMAPINFO* bmi;
cv::Mat image;
};
void initDisplayParam(StDisplayWnd* wnd, HWND hwnd);
//
void Display(StDisplayWnd* wnd, cv::Mat& img);
void releaseDisplay(StDisplayWnd* wnd);
实现文件:
// implement file
// mylaf
void initDisplayParam(StDisplayWnd* wnd, HWND hwnd) { //
unsigned int buff_size = sizeof(BITMAPINFOHEADER) + 1024;
unsigned char* buff = new unsigned char[buff_size]; //
wnd->hwnd = hwnd;//GetDlgItem(id)->GetSafeHwnd();
wnd->hdc = ::GetDC(wnd->hwnd);
::GetWindowRect(wnd->hwnd, &wnd->rect); //
int dst_width = wnd->rect.right - wnd->rect.left;
int dst_height = wnd->rect.bottom - wnd->rect.top;
int dst_bpp = 24;// 8 * image.channels(); //
wnd->bmi = (BITMAPINFO*)buff;
BITMAPINFOHEADER* bmih = &(wnd->bmi->bmiHeader);
memset(bmih, 0, sizeof(*bmih));
bmih->biSize = sizeof(BITMAPINFOHEADER);
bmih->biWidth = dst_width;// image.cols;
bmih->biHeight = -dst_height;// -image.rows;
bmih->biPlanes = 1;
bmih->biBitCount = (unsigned short)dst_bpp;
bmih->biCompression = BI_RGB; //
if (dst_bpp == 8)
{
RGBQUAD* palette = wnd->bmi->bmiColors;
for (int i = 0; i < 256; i++)
{
palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
palette[i].rgbReserved = 0;
}
}
wnd->image = cv::Mat::zeros(dst_height, dst_width, CV_8UC3);
}
void Display(StDisplayWnd* wnd, cv::Mat& img) { // 图像缩放
resize(img, wnd->image, cv::Size(wnd->image.cols, wnd->image.rows)); //
::StretchDIBits(wnd->hdc,
0, 0, wnd->bmi->bmiHeader.biWidth, -wnd->bmi->bmiHeader.biHeight,
0, 0, wnd->image.cols, wnd->image.rows,
wnd->image.data, wnd->bmi, DIB_RGB_COLORS, SRCCOPY);
}
void releaseDisplay(StDisplayWnd* wnd)
{
::ReleaseDC(wnd->hwnd, wnd->hdc); unsigned char* buff = (unsigned char*)wnd->bmi;
delete[] buff;
}
收藏的代码:
/*
* 图像播放器
* Mylaf
*/
#ifndef _ME_IMAGEPLAYER_HEADER_
#define _ME_IMAGEPLAYER_HEADER_
#include "me_opencv_inc.h"
#include "Windows.h"
class CImagePlayer
{
public:
static const int BUFF_SIZE_BITMAPINFO = sizeof(BITMAPINFOHEADER) + 1024;
public:
CImagePlayer():hWnd(NULL),bmi(NULL){}
virtual ~CImagePlayer() { Release(); }
int Init(HWND hWnd)
{
this->hWnd = hWnd;
this->dcWnd = ::GetDC(hWnd);
::GetWindowRect(hWnd, &(this->rectWnd));
int dst_width = ((rectWnd.right - rectWnd.left + 3) >> 2) << 2;
int dst_height = rectWnd.bottom - rectWnd.top;
int dst_bpp = 24;// 8 * image.channels();
this->show = cv::Mat::zeros(dst_height, dst_width, CV_8UC3);
unsigned char* buff = new unsigned char[BUFF_SIZE_BITMAPINFO];
memset(buff, 0, BUFF_SIZE_BITMAPINFO);
this->bmi = (BITMAPINFO*)buff;
BITMAPINFOHEADER* bmih = &(this->bmi->bmiHeader);
memset(bmih, 0, sizeof(*bmih));
bmih->biSize = sizeof(BITMAPINFOHEADER);
bmih->biWidth = dst_width;// image.cols;
bmih->biHeight = -dst_height;// -image.rows;
bmih->biPlanes = 1;
bmih->biBitCount = (unsigned short)dst_bpp;
bmih->biCompression = BI_RGB;
if (dst_bpp == 8) {
RGBQUAD* palette = this->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;
}
}
return 0;
}
int ReSize(const cv::Mat& image)
{
RECT rc;
::GetWindowRect(hWnd, &rc);
int width = ((rc.right - rc.left) >> 2) << 2;
int height = rc.bottom - rc.top;
if (width != this->show.cols || height != this->show.rows)
{
BITMAPINFOHEADER* bmih = &(this->bmi->bmiHeader);
bmih->biWidth = width;// image.cols;
bmih->biHeight = -height;// -image.rows;
// 需要
this->show = cv::Mat::zeros(height, width, CV_8UC3);
}
return 0;
}
int ReColor(const cv::Mat& image)
{
BITMAPINFOHEADER* bmih = &(this->bmi->bmiHeader);
if (bmih->biBitCount != 8 * image.channels())
{
bmih->biBitCount = 8 * image.channels();
if (bmih->biBitCount == 8) {
RGBQUAD* palette = this->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;
}
}
}
return 0;
}
int Play(const cv::Mat& image)
{
if (this->hWnd == NULL || this->bmi == NULL) return -1;
ReSize(image);
ReColor(image);
// 图像缩放
resize(image, this->show, cv::Size(this->show.cols, this->show.rows));
// 贴图
::StretchDIBits(
this->dcWnd,
0, 0, this->bmi->bmiHeader.biWidth, -this->bmi->bmiHeader.biHeight,
0, 0, this->show.cols, this->show.rows,
this->show.data, this->bmi, DIB_RGB_COLORS, SRCCOPY);
return 0;
}
void Release(void) {
::ReleaseDC(this->hWnd, this->dcWnd);
unsigned char* buff = (unsigned char*)this->bmi;
delete[] buff;
this->bmi = NULL;
}
protected:
HWND hWnd; //
HDC dcWnd;
RECT rectWnd;
cv::Mat show;
BITMAPINFO* bmi;
};
#endif //_ME_IMAGEPLAYER_HEADER_