0

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.

Jean Valjean
  • 747
  • 1
  • 9
  • 30
  • You need to save the result of `SelectObject(hDCBits, hBit);` to an HBITMAP and then select it back into hDCBits before you delete the HDC. Failure to do so will cause resource-leaks. GDI handles are a limited resource. Also, since you're caching the images that you've loaded - you should add another variable, so that you only create and destroy the HDC once. You can get the initial bitmap that's selected in it with a call to `GetCurrentObject(hDCBits, OBJ_BITMAP);` so that (a) you only have to save a copy of it once and (b) you can restore this bitmap before finally destroying the HDC. – enhzflep Aug 16 '15 at 15:26

1 Answers1

-2

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.
}
Community
  • 1
  • 1
ProXicT
  • 1,903
  • 3
  • 22
  • 46
  • 3
    This is probably not going to happen. A possible reason could be: GDI+ won't get you any more performance. It's implemented in software, and will usually be slower than GDI. Performance improvements are more likely using the [Windows Imaging Component](https://msdn.microsoft.com/en-us/library/windows/desktop/ee719902.aspx) together with a [Direct2D](https://msdn.microsoft.com/en-us/library/windows/desktop/dd370990.aspx) rendering surface. – IInspectable Aug 15 '15 at 20:54
  • I still think, using GDI+ will perform better than plain winapi. Of course he can use some GPU accelerated libraries like OpenGL or Direct2D, but from what I've read he wants to do, GDI+ is enaugh. – ProXicT Aug 15 '15 at 21:35
  • 1
    [GDI **is** hardware accelerated](http://stackoverflow.com/q/9347532/1889329) (for the operations used in this question). Using `SmoothingModeHighQuality` with GDI+, however, will not take advantage of GPU hardware, and will be (significantly) slower than a plain GDI implementation. Thinking of it, maybe Direct2D doesn't improve performance for this simple scenario either. It would, though, if there were any processing/filtering involved. – IInspectable Aug 15 '15 at 22:18
  • Well, I know GDI+ does not have any HW acceleration. The code example I posted was just to help Jacob start with GDI+. I just think, GDI+ is good to use in his situation. – ProXicT Aug 15 '15 at 22:36
  • 4
    The question is asking for help, improving the performance. GDI+ is helpful for a lot of things, but it is not an answer to this question. – IInspectable Aug 15 '15 at 22:57
  • It doesn't sound like you really want an explanation for the down vote. It sounds more like you want it removed. When presented with a reason why your answer would be down voted you respond by ignoring the criticism. – David Heffernan Aug 16 '15 at 07:13
  • I don't want the downvote to be removed. I'm happy with that explanation but I think I can still argue about it. If it sounds like that, my bad. My English is not on that good, so my word dictionary is limited thus my arguments may sound inadequately. – ProXicT Aug 16 '15 at 11:04