I want to use the Windows clipboard image data in OpenCV
without using a temporary file.
Can I use imdecode
for this?
I tried this but Mat
was empty:
if(!IsClipboardFormatAvailable(CF_DIB)) return;
OpenClipboard(NULL);
HGLOBAL clipboard = GetClipboardData(CF_DIB);
if(clipboard){
char* data = (char*)GlobalLock(clipboard);
Mat buf = Mat(1, GlobalSize(clipboard), CV_8UC1, data, Mat::AUTO_STEP);
Mat mat = imdecode(buf, IMREAD_UNCHANGED);
GlobalUnlock(clipboard);
}
CloseClipboard();
CodePudding user response:
You seem to be missing the corresponding SetClipboardData
I don't know opencv but normally when I use the clipboard I write something like this
const auto opened = OpenClipboard(GetConsoleWindow());
if (opened)
{
EmptyClipboard();
const std::string command{"hello clipboard"};
auto* const hMem = GlobalAlloc(GMEM_MOVEABLE, (command.size() 1));
if (hMem == nullptr)
{
CloseClipboard();
return;
}
auto* const p = static_cast<LPSTR>(GlobalLock(hMem));
if (p)
{
memcpy_s(p, command.size(), command.data(), command.size());
p[command.size()] = 0;
GlobalUnlock(hMem);
SetClipboardData(CF_TEXT, p); <<<<<
}
CloseClipboard();
}
disclaimer : removed error handling and printouts
CodePudding user response:
You should be able to use CF_BITMAP
to get the handle to HBITMAP
. Then use GetDIBits
to copy HBITMAP
to cv::Mat
memory.
If for some reason CF_BITMAP
is not available, see this example for CF_DIB
backup, or check to see which format is available.
void copy()
{
cv::Mat mat;
HBITMAP hbitmap = nullptr;
if (!::OpenClipboard(nullptr))
return;
if (IsClipboardFormatAvailable(CF_BITMAP))
hbitmap = (HBITMAP)GetClipboardData(CF_BITMAP);
if(!hbitmap && IsClipboardFormatAvailable(CF_DIB))
{
HANDLE handle = GetClipboardData(CF_DIB);
LPVOID hmem = GlobalLock(handle);
if (hmem)
{
BITMAPINFO* bmpinfo = (BITMAPINFO*)hmem;
int offset = (bmpinfo->bmiHeader.biBitCount > 8) ?
0 : sizeof(RGBQUAD) * (1 << bmpinfo->bmiHeader.biBitCount);
BYTE* bits = (BYTE*)(bmpinfo) bmpinfo->bmiHeader.biSize offset;
HDC hdc = ::GetDC(0);
hbitmap = CreateDIBitmap(hdc,
&bmpinfo->bmiHeader, CBM_INIT, bits, bmpinfo, DIB_RGB_COLORS);
::ReleaseDC(0, hdc);
GlobalUnlock(hmem);
}
}
if (hbitmap)
{
BITMAP bm;
::GetObject(hbitmap, sizeof(bm), &bm);
int cx = bm.bmWidth;
int cy = bm.bmHeight;
mat.create(cy, cx, CV_8UC4);
BITMAPINFOHEADER bi = { sizeof(bi), cx, -cy, 1, 32, BI_RGB };
GetDIBits(hdc, hbitmap, 0, cy, mat.data, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
}
CloseClipboard();
}