arch3r
arch3r

Reputation: 56

How to extract a part of HBITMAP without using BitBlt

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!

Upvotes: -2

Views: 1334

Answers (1)

Barmak Shemirani
Barmak Shemirani

Reputation: 31629

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.

Upvotes: 1

Related Questions