c++winapibitmapgdistretchblt

C++ Win32: Speeding up Bitmap Operations


I'm looking to speed up a Bitmap displaying program. It's not dreadfully slow, I just think it could be faster. I run it in a Win32 environment. Here's the code:

void load(LPCWSTR file, int i) {
    hBitmap[i] = (HBITMAP)::LoadImage(NULL, file, IMAGE_BITMAP, 0, 0,
        LR_LOADFROMFILE);
    GetObject(hBitmap[i], sizeof(BITMAP), (LPSTR)&hSize[i]);
}
void newBit(int i, int x, int y, HDC hdc) {

    BITMAP Bitmap = hSize[i];
    HBITMAP hBit = hBitmap[i];

    HDC hDCBits = CreateCompatibleDC(hdc);
    SelectObject(hDCBits, hBit);
    StretchBlt(hdc, x, y, Bitmap.bmWidth, Bitmap.bmHeight,
        hDCBits, 0, 0, Bitmap.bmWidth, Bitmap.bmHeight, SRCCOPY);
    DeleteDC(hDCBits);
}

I run the "Load" function in the beginning, and I'm okay with how long it takes. I run the newBit function whenever in the program that I need to. I specifically use the stretchBlt command because I need the resizing capability. Any insight into what I'm doing wrong and what I could improve would be appreciated.


Solution

  • Since I suspect it has to do something with your previous question here, I post following answer.

    If you want to create some animation in your window and want to speed things up, consider using GDI+ instead just plain winapi. With GDI+ you just put your drawing methods in WM_PAINT message and update your scene with invalidating your control rect and updating the window.
    For example something like that:

    InvalidateRect(hwnd, NULL, TRUE);
    UpdateWindow(hwnd);
    

    WM_PAINT message handling could look like this for example:

    case WM_PAINT:
    {
        /************************************************************************/
        /* Initialize                                                           */
        /************************************************************************/
        hdc = BeginPaint(hwnd, &ps);
        Graphics graphics(hdc);
        Bitmap *pMemBitmap = new Bitmap(rect.right, rect.bottom);
        Graphics* pMemGraphics = Graphics::FromImage(pMemBitmap);
        SolidBrush back(Color(0, 0, 0));
        pMemGraphics->FillRectangle(&back, 0, 0, rect.right, rect.bottom); // Fill your background with some color
        pMemGraphics->SetSmoothingMode(SmoothingModeHighQuality); // Set your raster quality
        graphics.SetSmoothingMode(SmoothingModeHighQuality);
    
        // Rotate some primitive around your screen
        static double x = M_PI + M_PI / 2;
        x += 0.03f;
    
        if(x > M_PI * 2)
        {
            x = 0;
        }
        double posX = cos(x);
        double posY = sin(x);
    
        Pen pen(Color(255, 255, 255, 0), 5);
        pMemGraphics->DrawEllipse(&pen, (int)(posX * 50 - 15 + rect.right / 2), (int)(posY * 50 - 15 + rect.bottom / 2), 30, 30);
        graphics.DrawImage(pMemBitmap, 0, 0); // Draw the entire bitmap to screen (double buffering)
    
        /************************************************************************/
        /* Cleanup                                                              */
        /************************************************************************/
        delete pMemGraphics;
        delete pMemBitmap;
        EndPaint(hwnd, &ps);
        break;
    }
    

    To avoid flickering, you should tell winapi not to erase background like so:

    case WM_ERASEBKGND:
    {
        return true; // Tell winapi, we already handled that.
    }