使用Bitmap / GDI表现缓慢

时间:2014-04-18 00:52:46

标签: optimization bitmap gdi+

行。 我想这样做:

while(1)
{
    CaptureScreenshot (as BMP)
    Convert screenshot to 24 bit instead of 32 bit
    Resize screenshot size 
    Get the BMP bits array of the resized screenshot
}

我有它的工作,但我能得到的最好的是每秒18次迭代(截图)。 我需要更多,我想请你帮我改进。

这就是我的所作所为:

Start()
{
    ULONG_PTR gdiplusToken=0;
    HDC mhCompatibleDC;
    HBITMAP mhCompatibleBitmap;
    HWND mhDesktopWnd;
    HDC mhDesktopDC;
    byte*piRGB=new byte[1200*900*3]

    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    mhDesktopDC = GetDC(GetDesktopWindow());
    mhCompatibleDC = CreateCompatibleDC(mhDesktopDC);
    mhCompatibleBitmap = CreateCompatibleBitmap(mhDesktopDC, 1440, 900);
    SelectObject(mhCompatibleDC, mhCompatibleBitmap);
    moResizeImage = new Bitmap(1200, 900, PixelFormat24bppRGB);
    moGraphics = Gdiplus::Graphics::FromImage(moResizeImage);

    //as you can see to optimize the code, i pre allocate the CompatibleDC (which speed things)
    //I also use the same moGraphics and not creating moResizeImage again and again - BUT from my tests
    //that does not speed things so i guess that DrawImage reallocate moResizeImage memory on each call
    While(1)
    {
        BitBlt(mhCompatibleDC, 0, 0, 1440, 900, mhDesktopDC, 0, 0, SRCCOPY)
        Bitmap oOrgDesktopImage(mhCompatibleBitmap, NULL);//here i have the original desktop image 32 bit (as my display)
        moGraphics->DrawImage(&oOrgDesktopImage, 0, 0, 1200, 900);(here it converts it to 24 bit as i need and do the resize)

        //now I take the bits part of the BMP and copy it to piRGB
        Gdiplus::BitmapData bitmapData;
        Gdiplus::Rect rect(0, 0, 1200, 900);

        if (Gdiplus::Ok == moResizeImage->LockBits(&rect, Gdiplus::ImageLockModeRead , moResizeImage->GetPixelFormat(),&bitmapData))
        {
            int len = bitmapData.Height * std::abs(bitmapData.Stride);


            for (int i = 0; i < len; i = i + 1)//18
            {
                *piRGB = ((BYTE*)bitmapData.Scan0)[i++];
                piRGB++;
            }
            moResizeImage->UnlockBits(&bitmapData);

        }
    //here i do things with piRGB but these things are not counted it the timer so you can assume here the code ends 
    //as said as the code looks now, i can fill piRGB ~18 times (18loops) in 1 second. I must improve that/
    //my knowledge in GDI is very poor and i hope you can provide code to your suggestions - THANKS
    }

如果我们看看while部分,那么它每秒运行18次。 如果我删除了while中的所有代码而只留下了 BitBlt调用 然后我每秒得到300个循环。 如果我加了 位图oOrgDesktopImage(mhCompatibleBitmap,NULL); 我每秒得到160个循环。 如果我添加moGraphics-&gt; DrawImage(&amp; oOrgDesktopImage,0,0,1200,900)调用 我每秒得到19个循环。 添加其余代码(for循环)将其减少到18个循环

1 个答案:

答案 0 :(得分:0)

Start(){
    HDC mhCompatibleDC, mhDesktopDC, hdc;
    HBITMAP hBitmap, hBitmapOld;
    unsigned char *piRGB= NULL;
    int i;

    mhDesktopDC = GetDC(GetDesktopWindow());

    hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);
    mhCompatibleDC = CreateCompatibleDC(hdc);
    hBitmap = NewDIBSection(1200, 900, (void **)&piRGB);
    if(hBitmap == NULL){/* Error */}
    hBitmapOld = SelectObject(mhCompatibleDC, hBitmap);
    //Now piRGB points to RGB data of mhCompatibleDC
    DeleteDC(hdc);

    //SetStretchBltMode(mhCompatibleDC, HALFTONE); //for better quality


    for(i = 0; i < 200; i++){
        BitBlt(mhCompatibleDC, 0, 0, 1200, 900, mhDesktopDC, 0, 0, SRCCOPY);
        //StretchBlt(mhCompatibleDC, 0, 0, 1200, 900, mhDesktopDC, 0, 0, 1440, 900, SRCCOPY);
    }

    SelectObject(mhCompatibleDC, hBitmapOld);
    DeleteDC(mhCompatibleDC);
    DeleteObject(hBitmap);
    ReleaseDC(GetDesktopWindow(), mhDesktopDC);
}

HBITMAP NewDIBSection(int cx, int cy, void **ppBits){
    HBITMAP hbitmap = NULL;
    LPBITMAPINFO lpbmi;
    HDC hdc;

    lpbmi = (LPBITMAPINFO)calloc(1, sizeof (BITMAPINFO) + 4 * sizeof(DWORD));
    if(!lpbmi){return NULL;}

    ZeroMemory(&lpbmi->bmiHeader, sizeof(BITMAPINFOHEADER));
    lpbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    lpbmi->bmiHeader.biWidth = cx;
    lpbmi->bmiHeader.biHeight = -cy;
    lpbmi->bmiHeader.biPlanes = 1;
    lpbmi->bmiHeader.biBitCount = 24;
    lpbmi->bmiHeader.biCompression = BI_RGB;

    hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);
    hbitmap = CreateDIBSection(hdc, lpbmi, DIB_RGB_COLORS, ppBits, NULL, 0);

    DeleteDC(hdc);
    free(lpbmi);

    return hbitmap;
}

测试结果:

BitBlt -> 368 msec
StretchBlt -> 2,5 - 3,6 sec!

瓦尔特