Mat轉HBITMAP CBitmap

本轉換代碼從opencv源碼 imshow中提取並改造而成 源碼來自與opencv4庫 與openCV3有些許不同這裏給出內部用到的轉換代碼

,拿到HBITMAP句柄後 再使用 CBitmap m_bitmap; m_bitmap.Attach(hbmp);便可以轉換爲CBitmap對象

HBITMAP MattoHBMP(cv::Mat & Image)
{
	HBITMAP hbmp = NULL;
	SIZE size = { Image.cols ,Image.rows };
	const int channels = 3;
	int bpp = Image.channels() * 8;
	assert(Image.rows >= 0 && Image.cols >= 0 && (bpp == 8 || bpp == 24 || bpp == 32));
	unsigned char buffer[sizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD)];
	BITMAPINFO* bmi = (BITMAPINFO*)buffer;
	//搞不懂這裏爲什麼反轉與下面的flip不是重複了麼
	FillBitmapInfo(bmi, size.cx, size.cy, channels * 8, 0);
	void* dst_ptr = 0;
	hbmp = CreateDIBSection(NULL, bmi, DIB_RGB_COLORS, (void **)&dst_ptr/*&pBits*/, NULL, 0);
	if (Image.channels() == 1)
		SetBitmapBits(hbmp, (DWORD)Image.total(), Image.data);
	else
	{
		cv::Mat dst(size.cy, size.cx, CV_8UC3, dst_ptr, (size.cx * channels + 3) & -4);
		//Image.copyTo(dst);
		convertToShow(Image, dst, false);
		CV_Assert(dst.data == (uchar*)dst_ptr);
		//cv::flip(dst, dst, 0);
	}
	return hbmp;
}

下面的FiilBitmapInfo爲庫中源碼 無任何修改


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;
		}
	}
}

接下來還有轉換代碼 均摘抄自openCV420

inline void CLayerData::convertToShow(const cv::Mat &src, cv::Mat &dst, bool toRGB)
{
	const int src_depth = src.depth();
	CV_Assert(src_depth != CV_16F && src_depth != CV_32S);
	cv::Mat tmp;
	switch (src_depth)
	{
	case CV_8U:
		tmp = src;
		break;
	case CV_8S:
		cv::convertScaleAbs(src, tmp, 1, 127);
		break;
	case CV_16S:
		cv::convertScaleAbs(src, tmp, 1 / 255., 127);
		break;
	case CV_16U:
		cv::convertScaleAbs(src, tmp, 1 / 255.);
		break;
	case CV_32F:
	case CV_64F: // assuming image has values in range [0, 1)
		src.convertTo(tmp, CV_8U, 255., 0.);
		break;
	}
	cv::cvtColor(tmp, dst, toRGB ? cv::COLOR_BGR2RGB : cv::COLOR_BGRA2BGR, dst.channels());
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章