Last active
February 6, 2022 21:56
-
-
Save AhiyaHiya/6e455a3a6c846766f1017044131bfab7 to your computer and use it in GitHub Desktop.
Function to convert cv::Mat to Win32 HBITMAP aka BMP; function to paste HBITMAP to Windows clipboard.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cassert> | |
#include "opencv2/opencv.hpp" | |
auto ConvertCVMatToBMP (cv::Mat frame) -> HBITMAP | |
{ | |
auto convertOpenCVBitDepthToBits = [](const int32_t value) | |
{ | |
auto regular = 0u; | |
switch (value) | |
{ | |
case CV_8U: | |
case CV_8S: | |
regular = 8u; | |
break; | |
case CV_16U: | |
case CV_16S: | |
regular = 16u; | |
break; | |
case CV_32S: | |
case CV_32F: | |
regular = 32u; | |
break; | |
case CV_64F: | |
regular = 64u; | |
break; | |
default: | |
regular = 0u; | |
break; | |
} | |
return regular; | |
}; | |
auto imageSize = frame.size(); | |
assert(imageSize.width && "invalid size provided by frame"); | |
assert(imageSize.height && "invalid size provided by frame"); | |
if (imageSize.width && imageSize.height) | |
{ | |
auto headerInfo = BITMAPINFOHEADER{}; | |
ZeroMemory(&headerInfo, sizeof(headerInfo)); | |
headerInfo.biSize = sizeof(headerInfo); | |
headerInfo.biWidth = imageSize.width; | |
headerInfo.biHeight = -(imageSize.height); // negative otherwise it will be upsidedown | |
headerInfo.biPlanes = 1;// must be set to 1 as per documentation frame.channels(); | |
const auto bits = convertOpenCVBitDepthToBits( frame.depth() ); | |
headerInfo.biBitCount = frame.channels() * bits; | |
auto bitmapInfo = BITMAPINFO{}; | |
ZeroMemory(&bitmapInfo, sizeof(bitmapInfo)); | |
bitmapInfo.bmiHeader = headerInfo; | |
bitmapInfo.bmiColors->rgbBlue = 0; | |
bitmapInfo.bmiColors->rgbGreen = 0; | |
bitmapInfo.bmiColors->rgbRed = 0; | |
bitmapInfo.bmiColors->rgbReserved = 0; | |
auto dc = GetDC(nullptr); | |
assert(dc != nullptr && "Failure to get DC"); | |
auto bmp = CreateDIBitmap(dc, | |
&headerInfo, | |
CBM_INIT, | |
frame.data, | |
&bitmapInfo, | |
DIB_RGB_COLORS); | |
assert(bmp != nullptr && "Failure creating bitmap from captured frame"); | |
return bmp; | |
} | |
else | |
{ | |
return nullptr; | |
} | |
} | |
auto PasteBMPToClipboard(void* bmp) -> bool | |
{ | |
assert(bmp != nullptr && "You need a bmp for this function to work"); | |
if (OpenClipboard(NULL) && bmp != nullptr) | |
{ | |
EmptyClipboard(); | |
SetClipboardData(CF_BITMAP, bmp); | |
CloseClipboard(); | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
int main(int argc, char const *argv[]) | |
{ | |
auto emptyFrame = cv::Mat{}; | |
auto bmp = ConvertCVMatToBMP(emptyFrame); | |
if (bmp) | |
{ | |
auto pasteResult = PasteBMPToClipboard(bmp); | |
(void)pasteResult; // examine result at your convenience | |
DeleteObject(bmp); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
auto dc = GetDC(nullptr); I get error for this. 'too many arguments in function call'
how come?
But i solved it when i use :
CDC* p = GetDC();
HDC dc = p->m_hDC;
Then i tried to display the HBITMAP using the following code but its not showing anything. Do you know why? thanks.
m_pic.GetClientRect(&rectStaticClient);
rectStaticClient.NormalizeRect();
m_size.cx = rectStaticClient.Size().cx;
m_size.cy = rectStaticClient.Size().cy;
m_size.cx = rectStaticClient.Width(); // zero based
m_size.cy = rectStaticClient.Height(); // zero based