-2

I have a HBITMAP object. Without using BitBlt I would like to divide it into parts and obtain either the bits or new bitmaps of these parts

I can do it with BitBlt, but it is slow. It takes ~50 ms for extracting the part. I have considered extracting regions of the byte array obtained from the bitmap, but this seems difficult. Is there any other way?

Thanks!

arch3r
  • 56
  • 9
  • see here http://stackoverflow.com/a/35763157/4603670 – Barmak Shemirani Mar 28 '16 at 13:44
  • @BarmakShemirani : Thank you for sharing the link! How exactly can I extend that to copy a region? If the `HBITMAP` is 1920X1080, I'd like to take 500X500 sections from the byte array using memcpy. I'm still not able to understand the arrangement of the pixels. Any link elaborating that? Thanks! – arch3r Mar 29 '16 at 11:41
  • I posted link to my own post, where I explain how to access the bits directly. Anyway, `BitBlt` is faster and more reliable, and it doesn't take 50 ms for doing that. Show what you have done already so we can see where it goes wrong... – Barmak Shemirani Mar 29 '16 at 14:29
  • @BarmakShemirani : Please find the code for `BitBlt` [here](http://pastebin.com/XX7xnwDy) I am capturing parts of the screen (something like a grid) using threads. Each of this takes between 50-100 ms I have also tried getting an existing `HBITMAP`, creating a `DC` for it and using `BitBlt` to capture parts of it (rather than capturing from `hDesktopDC`) but it didn't make a difference. – arch3r Mar 31 '16 at 04:31

1 Answers1

1

BitBlt is very fast. If you are copying from another dc it takes a little too long. There is no way to get around that.

To word directly with pixels you need GetDIBits(HDC hdc, HBITMAP hbitmap...) but you still need BitBlt in order to setup the hbitmap

You can create a second memory dc, copy from first memory dc to second memory dc, this will be much faster. Using memory device context is like accessing bits directly.

#include <iostream>
#include <windows.h>

using namespace std;

long long milliseconds()
{
    LARGE_INTEGER fq, t;
    QueryPerformanceFrequency(&fq);
    QueryPerformanceCounter(&t);
    return 1000 * t.QuadPart / fq.QuadPart;
}

int main()
{
    HWND hwnd = GetDesktopWindow();
    HDC hdc = GetDC(hwnd);
    HDC memdc = CreateCompatibleDC(hdc);
    RECT rc;
    GetWindowRect(hwnd, &rc);
    int width = rc.right - rc.left;
    int height = rc.bottom - rc.top;

    int xPos = 100;
    int yPos = 100;
    int cropWidth = 500;
    int cropHeight = 500;

    HBITMAP hbitmap = CreateCompatibleBitmap(hdc, width, height);
    SelectObject(memdc, hbitmap);

    long long start;

    start = milliseconds();
    BitBlt(memdc, 0, 0, cropWidth, cropHeight, hdc, xPos, yPos, SRCCOPY);
    //this will take about 50 ms, or much less
    cout << milliseconds() - start << "\n"; 

    {
        //create a second memory dc:
        start = milliseconds();
        HDC memdc2 = CreateCompatibleDC(hdc);
        HBITMAP hbitmap2 = CreateCompatibleBitmap(memdc2, 500, 500);
        SelectObject(memdc2, hbitmap2);
        BitBlt(memdc2, 0, 0, 500, 500, memdc, 0, 0, SRCCOPY);

        //this will take about 1 ms:
        cout << "time: " << milliseconds() - start << "\n";
        DeleteObject(hbitmap2);
        DeleteDC(memdc2);
    }

    DeleteDC(memdc);
    DeleteObject(hbitmap);
    ReleaseDC(hwnd, hdc);

    return 0;
}

For the small you have shown it shouldn't be necessary to either access bits directly, or to use a second memory dc. You can copy any portion of the screen directly, it will only need 1 BitBlt operation.

Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77