天天看點

WinCE顯示資源中BMP圖檔的幾種方法

      前面介紹了如何直接操作WinCE的FrameBuffer,這裡将介紹一種通過寫FrameBuffer顯示資源中BMP圖檔的方法。并與使用GDI做一個比較,看看直接讀寫FrameBuffer是否能提高效率?

      采用GDI的方法,關鍵代碼如下:

    hScrDC = CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL);

    hMemDC = CreateCompatibleDC (hScrDC);

    bmp.LoadBitmap(MAKEINTRESOURCE(IDB_BITMAP1));

    bmp.GetBitmap(&bmpInfo); 

    SelectObject(hMemDC,bmp);

    BitBlt(hScrDC,0,0,dwWidth,dwHeight,hMemDC,0,0,SRCCOPY);

       采用直接寫FrameBuffer的方法,關鍵代碼如下:

    HINSTANCE hInst = (HINSTANCE)::GetModuleHandle(NULL);

    HRSRC hrc = FindResource((HMODULE)hInst,MAKEINTRESOURCE(IDB_BITMAP1),RT_BITMAP);

    HGLOBAL hGlobal = LoadResource(NULL,hrc);

    dwBufSize = ::SizeofResource(NULL,hrc);

    gbmpBuf = (PBYTE)::LockResource(hGlobal);

    memcpy(gpLCDBuf,gbmpBuf,dwBufSize);

       資源中加載的BMP圖檔是從WinCE的顯存中直接儲存下來的,如下圖所示。

WinCE顯示資源中BMP圖檔的幾種方法

      使用BitBlt顯示的效果如下圖所示。

WinCE顯示資源中BMP圖檔的幾種方法

      直接寫顯存的效果如下圖所示。

WinCE顯示資源中BMP圖檔的幾種方法

      可以看到采用BitBlt,資源中的BMP似乎被真實顯示。采用直接寫屏的方法顔色被還原了,但往右偏了一些。他們分别使用的時間如下圖所示,GDI使用了145ms,直接寫顯存大概1ms。

WinCE顯示資源中BMP圖檔的幾種方法

      很明顯,直接寫顯存比使用BitBlt快很多,但位置有偏差。那麼用GDI能否有更快的方法?它為什麼這麼慢。又嘗試着用了GDI的另外一種方法顯示。代碼如下:

    bmi.bmih.biSize = sizeof(bmi.bmih);

    bmi.bmih.biWidth = dwWidth;

    bmi.bmih.biHeight = -dwHeight;

    bmi.bmih.biPlanes = 1;

    bmi.bmih.biBitCount = (BYTE)bmpInfo.bmBitsPixel;

    bmi.bmih.biSizeImage = 0;

    bmi.bmih.biXPelsPerMeter = 0;

    bmi.bmih.biYPelsPerMeter = 0;

    bmi.bmih.biClrUsed = 0;

    bmi.bmih.biClrImportant = 0;

    bmi.bmih.biCompression = BI_BITFIELDS;

    *(DWORD *)(&bmi.rgq[0]) = 0xF800;

    *(DWORD *)(&bmi.rgq[1]) = 0x07E0;

    *(DWORD *)(&bmi.rgq[2]) = 0x001F;

    StretchDIBits (hScrDC, 0, 0, dwWidth, dwHeight, 0, 0, dwWidth, dwHeight,

        gbmpBuf, (PBITMAPINFO)&bmi, DIB_RGB_COLORS, SRCCOPY);

   采用這種方法,顯示效果和DDraw完全一樣,速度也不相上下,同樣比BitBlt快很多。這是為什麼呢?玄妙就在bmi.rgq,這裡設定的BIT MASK與顯示驅動中一緻,是以,效果相當于直接寫屏,顔色也對了,效率也高了。而BitBlt預設的BIT MASK估計與驅動中的不一緻,進而導緻多做一些記憶體運算,花費了一些時間。為了驗證這個想法,修改bmi.rgq的設定如下:  

    *(DWORD *)(&bmi.rgq[1]) = 0x03E0;

   這種情況下,顔色顯示與BitBlt一樣,使用的時間也差不多。看來并不是使用GDI就一定會慢,BIT MASK才是關鍵。16位色的BIT MASK主要有以下幾種。

    // XRRRRRGG.GGGBBBBB 0x7C00 0x03E0 0x1F

    // RRRRRXGG.GGGBBBBB 0xF800 0x03E0 0x1F

    // RRRRRGGG.GGXBBBBB 0xF800 0x07C0 0x1F

    // RRRRRGGG.GGGBBBBB 0xF800 0x07E0 0x1F

    在實際開發過程中,這個小細節可以注意一下,也許可以提高一些效率。