opencv Mat显示到指定窗体 CImage实现

紧接着上一篇博文,因为direct2d的方式不够稳定,所以博主急需要找到其他的方法,实现把opencv的Mat显示到指定的窗体中。

本博文主要记录基于CImage类的实现。

1、要使用微软提供的CImage类需要包含头文件:

#include  

2、要使用的三个函数

(1)改变Mat图像的大小,以适应窗体

BOOL GetFixMat(const cv::Mat& src_img, cv::Mat& dst_img, unsigned int dc_heigh, unsigned int dc_width)
{
	if (!src_img.data)
	{
		return FALSE;
	}
	unsigned int img_rows(src_img.rows);
	unsigned int img_cols(src_img.cols);
	unsigned int fix_heigh(chaoMin(img_rows, dc_heigh));
	unsigned int fix_width(chaoMin(img_cols, dc_width));

	float ratio_w = static_cast(fix_width) / static_cast(img_cols);
	float ratio_h = static_cast(fix_heigh) / static_cast(img_rows);
	float ratio = chaoMin(ratio_w, ratio_h);

	int show_width = static_cast(ratio * img_cols);
	int show_height = static_cast(ratio * img_rows);

	cv::resize(src_img, dst_img, cv::Size(show_width, show_height), (0.0), (0.0), cv::INTER_LINEAR);

	return TRUE;
}


(2)将Mat转换成CImage

BOOL ConvertMat2CImage(const cv::Mat& src_img, CImage& dst_img)
{
	if (!src_img.data)
	{
		return FALSE;
	}
	int width = src_img.cols;           //获取输入图像的宽度  
	int height = src_img.rows;          //获取输入图像的高度  
	int channels = src_img.channels();  //获取输入图像的  
	int src_type = src_img.type();

	dst_img.Destroy();

	switch (src_type)
	{
	case CV_8UC1:
	{
		dst_img.Create(width, -1 * height, 8 * channels);
		unsigned char* dst_data = static_cast(dst_img.GetBits());
		int step_size = dst_img.GetPitch();     //获取位图行与行之间相差的字节数  
		unsigned char* src_data = nullptr;
		for (int i = 0; i < height; i++)
		{
			src_data = const_cast(src_img.ptr(i));   //获取行指针  
			for (int j = 0; j < width; j++)
			{
				if (step_size > 0)
				{
					*(dst_data + step_size*i + j) = *src_data++;
				}   //像素的排列方式是自左上开始的  
				else
				{
					*(dst_data + step_size*i - j) = *src_data++;
				}
			}
		}
		break;
	}
	case CV_8UC3:
	{
		dst_img.Create(width, height, 8 * channels);
		unsigned char* dst_data = static_cast(dst_img.GetBits());
		int step_size = dst_img.GetPitch();     //获取位图行与行之间相差的字节数  
		unsigned char* src_data = nullptr;
		for (int i = 0; i < height; i++)
		{
			src_data = const_cast(src_img.ptr(i));   //获取行指针  
			for (int j = 0; j < width; j++)
			{
				for (int k = 0; k < 3; k++)
				{
					*(dst_data + step_size*i + j * 3 + k) = src_data[3 * j + k];
				}
			}
		}
		break;
	}
	default:
		MessageBox(NULL, _T("输入的图像类型出错"), _T("提示"), MB_ICONINFORMATION | MB_OK);
		break;
	}

	return TRUE;
}

(3)将CImage显示到窗体

BOOL Show2DC(const cv::Mat& img, HDC dst_hdc, unsigned int dc_heigh, unsigned int dc_width)
{
	if (!img.data)
	{
		return FALSE;
	}
	CImage dst_img;
	cv::Mat temp;   //定义中间变量  
	GetFixMat(img, temp, dc_heigh, dc_width);  //图像的几何大小变换  
	ConvertMat2CImage(temp, dst_img);          //图像转换  
	int offsetx = (dc_width - temp.cols) / 2;           //调整偏移量  
	int offsety = (dc_heigh - temp.rows) / 2;
	BOOL temp1 = dst_img.Draw(dst_hdc, offsetx, offsety, dst_img.GetWidth(), dst_img.GetHeight());  //图像显示  

	return TRUE;
}

3、调用示例

void getHanle(HWND formhandle, int HDCwidth, int HDCheight)//记录传过来的窗体句柄,和窗体大小
{
	windowHDC = GetDC(formhandle);//传过来HWND,得到窗体HDC,
	windowHeight = HDCheight;
	windowwidth = HDCwidth;
}

void showImage()
{
	int idx = 1;
	while (true)
	{
		if (idx > 3) idx = 1;
		char filename[100];
		sprintf_s(filename, "%d.bmp", idx);
		Mat image = imread(filename);
		if (image.empty()) continue;

		Show2DC(image, windowHDC, windowHeight, windowwidth);
		idx++;
		Sleep(100);
	}
}

4、完毕。并且CImage类的方式,在win7最简单的系统上都可以使用。

over

祝大家编程快乐!


你可能感兴趣的:(Mat,读写显示操作)