Home > Enterprise >  Can imdecode be used to clipboard image?
Can imdecode be used to clipboard image?

Time:09-17

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();
}
  • Related