gdi+ Graphics::DrawImage really slow~~

后端 未结 9 999
一个人的身影
一个人的身影 2020-12-13 10:48

I am using a GDI+ Graphic to draw a 4000*3000 image to screen, but it is really slow. It takes about 300ms. I wish it just occupy less than 10ms.

Bitmap *bit         


        
9条回答
  •  醉梦人生
    2020-12-13 11:23

    /* First sorry for ma English, and the code is partly in polish, but it's simple to understand. I had the same problem and I found the best solution. Here it is.

    Dont use: Graphics graphics(hdc); graphics.DrawImage(gpBitmap, 0, 0); It is slow.

    Use: GetHBITMAP(Gdiplus::Color(), &g_hBitmap) for HBITMAP and draw using my function ShowBitmapStretch().

    You can resize it and it is much faster! Artur Czekalski / Poland

    */

    //--------Global-----------
    Bitmap *g_pGDIBitmap; //for loading picture
    int gRozXOkna, gRozYOkna; //size of working window
    int gRozXObrazu, gRozYObrazu; //Size of picture X,Y
    HBITMAP g_hBitmap = NULL; //for displaying on window
    //------------------------------------------------------------------------------
    int ShowBitmapStretch(HDC hdc, HBITMAP hBmp, int RozX, int RozY, int RozXSkal, int RozYSkal, int PozX, int PozY) 
    {
        if (hBmp == NULL) return -1;
        HDC hdc_mem = CreateCompatibleDC(hdc); //utworzenie kontekstu pamięciowego
        if (NULL == hdc_mem) return -2;
        //Trzeba połączyć BMP z hdc_mem, tzn. umieścić bitmapę w naszym kontekście pamięciowym
        if (DeleteObject(SelectObject(hdc_mem, hBmp)) == NULL) return -3; 
    
        SetStretchBltMode(hdc, COLORONCOLOR); //important! for smoothness
        if (StretchBlt(hdc, PozX, PozY, RozXSkal, RozYSkal, hdc_mem, 0, 0, RozX, RozY, SRCCOPY) == 0) return -4;
    
        if (DeleteDC(hdc_mem) == 0) return -5;
        return 0; //OK
    }
    //---------------------------------------------------------------------------
    void ClearBitmaps(void)
    {
        if (g_hBitmap) { DeleteObject(g_hBitmap);  g_hBitmap = NULL; }
        if (g_pGDIBitmap) { delete g_pGDIBitmap;  g_pGDIBitmap = NULL; }
    }
    //---------------------------------------------------------------------------
    void MyOpenFile(HWND hWnd, szFileName)
    {
        ClearBitmaps(); //Important!
        g_pGDIBitmap = new Bitmap(szFileName); //load a picture from file
    
        if (g_pGDIBitmap == 0) return;
        //---Checking if picture was loaded
        gRozXObrazu = g_pGDIBitmap->GetWidth();
        gRozYObrazu = g_pGDIBitmap->GetHeight();
        if (gRozXObrazu == 0 || gRozYObrazu == 0) return;
    
        //---Uworzenie bitmapy do wyświatlaia; DO IT ONCE HERE!
        g_pGDIBitmap->GetHBITMAP(Gdiplus::Color(), &g_hBitmap); //creates a GDI bitmap from this Bitmap object
        if (g_hBitmap == 0) return;
    
        //---We need to force the window to redraw itself
        InvalidateRect(hWnd, NULL, TRUE);
        UpdateWindow(hWnd);
    }
    //---------------------------------------------------------------------------
    void MyOnPaint(HDC hdc, HWND hWnd) //in case WM_PAINT; DO IT MANY TIMES
    {
        if (g_hBitmap)
        {
            double SkalaX = 1.0, SkalaY = 1.0; //scale
            if (gRozXObrazu > gRozXOkna || gRozYObrazu > gRozYOkna || //too big picture, więc zmniejsz; 
               (gRozXObrazu < gRozXOkna && gRozYObrazu < gRozYOkna)) //too small picture, można powiększyć 
            {
                SkalaX = (double)gRozXOkna / (double)gRozXObrazu; //np. 0.7 dla zmniejszania; FOR DECREASE
                SkalaY = (double)gRozYOkna / (double)gRozYObrazu; //np. 1.7 dla powiększania; FOR INCREASE
                if (SkalaY < SkalaX) SkalaX = SkalaY; //ZAWSZE wybierz większe skalowanie, czyli mniejszą wartość i utaw w SkalaX
            }
    
        if (ShowBitmapStretch(hdc, g_hBitmap, gRozXObrazu, gRozYObrazu, (int)(gRozXObrazu*SkalaX), (int)(gRozYObrazu*SkalaX), 0, 0, msg) < 0) return;
    

提交回复
热议问题