-
-
Save AhiyaHiya/6e455a3a6c846766f1017044131bfab7 to your computer and use it in GitHub Desktop.
#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; | |
} |
the problem can be happened that if the mat ' s cols is Not a multiple of 4
so when i resize the mat
resize(frame, frame, Size(frame.cols / 4 * 4, frame.rows));
it correctly work!
and then i want you to Explain what is the real inner of this problem.
and finish to find a way keep the orginal size of the mat.
@AhiyaHiya
when i translate gray mat into bitmap,
it become all blcak?
it happens always, you can check it!
please fix it!!!
I'm not keen on your coding style, but after a cosmetic cleanup, this example works just great.
The only thing I would suggest is that you release the device context using...
ReleaseDC(nullptr,dc);
The documentation is clear. Without that call you have a GDI handle leak.
Thanks for the timesaver.
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
// Convert to screen coordinates using static as base,
// then to DIALOG (instead of static) client coords
// using dialog as base
m_pic.ClientToScreen(&rectStaticClient);
ScreenToClient(&rectStaticClient);
m_pt.x = rectStaticClient.left;
m_pt.y = rectStaticClient.top;
GetObject(m_hBmpNew, sizeof(BITMAP), &m_bmInfo);
VERIFY(m_hBmpOld = (HBITMAP)SelectObject(m_dcMem, m_hBmpNew));
offsetx = m_pt.x;
offsety = m_pt.y;
InvalidateRect(&rectStaticClient);
@AhiyaHiya
the image is Oblique,
i had no idea to modify the bitmap 's stride.
how to fix it?