天天看點

Windows Mobile 顯示PNG圖檔

最近在跟長時間Suspend回來後,按Send/End鍵Sometimes不能用的BUG. 本人認為不關應用什麼事, 雖然PhoneCanvas部分是我做的. 但

驅動那邊人就是要我來跟, 唉,沒辦法,寫了一個hook Send/End鍵的應用來跟,看COM有沒有列印相關消息,來判斷按鍵消息是否傳到了上層,

是以就有了些時間來搞一下PNG顯示. MSFT有IImage來顯示圖檔, 但如果直接Draw出來的話, 每次都要花大量的時間來解碼,是以就感覺會慢. Google了一下,有人說把PNG轉成PARGB,然後再畫出來,會快很多.  是以就自己試了一下這個方法, 感覺還不錯哦。 

先用IImage接口把PNG轉成PARGB Bitmap并存起來, 然後再根據需要将圖檔畫出來就OK了...

#include <imaging.h>

#include <initguid.h>

#include <imgguids.h>

#pragma comment(lib,"Imaging.lib")

#pragma comment(lib,"uuid.lib")

typedef struct _tagPARGBImageInfo

{

    UINT Width;             // the Width of the image

    UINT Height;            // the Height of the image

    HBITMAP hBitMap;    // the Handle of the PARGB image

}PARGBImageInfo;

PARGBImageInfo g_PARGBImageInfo = {0};

// load png and create a PARGB Bitmap

void Load_PNG2PARGBBitmap()

{

    IImagingFactory *pImgFactory = NULL;

    IImage *pImage                 = NULL;

    // Normally you would only call CoInitialize/CoUninitialize

    // once per thread.  This sample calls CoInitialize in this

    // draw function simply to illustrate that you must call

    // CoInitialize before calling CoCreateInstance.

    CoInitializeEx(NULL, COINIT_MULTITHREADED);

    // Create the imaging factory.

    if (SUCCEEDED(CoCreateInstance (CLSID_ImagingFactory,

        NULL,

        CLSCTX_INPROC_SERVER,

        IID_IImagingFactory,

        (void **)&pImgFactory)))

    {

        INT nTimer = GetTickCount();

        // Load the image from the png file and get the image info

        if (SUCCEEDED(pImgFactory->CreateImageFromFile(TEXT("//My Documents//test.png"), &pImage)))

        {

            ImageInfo imgInfo = {0};

            // Get the image info

            if (SUCCEEDED(pImage->GetImageInfo(&imgInfo)))

            {

                BitmapData bmpData           = {0};

                IBitmapImage *pBitmapImage = NULL;

                RECT rc                       = {0, 0, imgInfo.Width, imgInfo.Height};

                // Save the image Width and Height

                g_PARGBImageInfo.Width = imgInfo.Width;

                g_PARGBImageInfo.Height = imgInfo.Height;

                // Create a bitmap image from an IImage object

                if (SUCCEEDED(pImgFactory->CreateBitmapFromImage(pImage, 0, 0, PIXFMT_32BPP_PARGB, InterpolationHintDefault, &pBitmapImage)))

                {

                    // Lock an area of a bitmap image object and access bitmap data in the specified pixel format

                    pBitmapImage->LockBits(&rc, ImageLockModeRead, PIXFMT_32BPP_PARGB, &bmpData);

                    // Create a bitmap with the specified width, height, and bit depth. And Save the Bitmap handle

                    g_PARGBImageInfo.hBitMap = CreateBitmap(imgInfo.Width, imgInfo.Height, 1, GetPixelFormatSize(imgInfo.PixelFormat), bmpData.Scan0);

                    ASSERT(g_PARGBImageInfo.hBitMap);

                    // Unlock an area of the bitmap image object locked by a previous call to the IBitmapImage::LockBits call

                    pBitmapImage->UnlockBits(&bmpData);

                    pBitmapImage->Release();

                }

            }

            pImage->Release();

        }

        DEBUGMSG(1, (TEXT("...Load_PNG2PARGBBitmap...Timer = %d....../r/n"), GetTickCount()-nTimer));

        pImgFactory->Release();

    }

    // Close the OLE Component Object Model (COM) library, freeing any resources that it maintains.

    CoUninitialize();

}

// draw PARGB Bitmap

void DrawImage_PARGB(HDC hdc)

{

    INT nTimer = GetTickCount();

    // draw image

    HDC hdcMem                = ::CreateCompatibleDC(hdc);

    HGDIOBJ hGdiObjOld        = ::SelectObject(hdcMem, g_PARGBImageInfo.hBitMap);

    // AlphaBlend the hdcTemp data to the hdc

    BLENDFUNCTION blendFunction = {0};

    blendFunction.AlphaFormat = AC_SRC_ALPHA;

    blendFunction.BlendFlags = 0;

    blendFunction.BlendOp = AC_SRC_OVER;

    blendFunction.SourceConstantAlpha = 255; //0-255 (透明度設定, 可以用于圖檔的漸變顯示 (^v^; )

    // Alpha Blend to hdcTemp

    AlphaBlend(hdc, 0, 0, g_PARGBImageInfo.Width, g_PARGBImageInfo.Height,

        hdcMem, 0, 0, g_PARGBImageInfo.Width, g_PARGBImageInfo.Height, blendFunction);

    ::SelectObject(hdcMem, hGdiObjOld);

    if (hdcMem)

    {

        DeleteDC(hdcMem);

        hdcMem = NULL;

    }

    DEBUGMSG(1, (TEXT("...DrawImage_PARGB...Draw PNG Timer = %d....../r/n"), GetTickCount()-nTimer));

}

測試DEBUG模式下512X512(186KB) PNG對比:

用直接Draw出來:

...DrawImage_ImageDraw.....Draw PNG Timer = 124......

// Draw the image.

INT nTimer = GetTickCount();

pImage->Draw(hdc, &rc, NULL);

DEBUGMSG(1, (TEXT("...DrawImage_ImageDraw.....Draw PNG Timer = %d....../r/n"), GetTickCount()-nTimer));

先轉換,然後畫出來:

...Load_PNG2PARGBBitmap...Timer = 121......

...DrawImage_PARGB...Draw PNG Timer = 15......

// Load and Draw the image.

Load_PNG2PARGBBitmap();

DrawImage_PARGB(GetDC(hWnd));

Merry Christmas :&)

Jacky Lee

2009-12-25