SHLoadImageFile與IImage

最近在調整軟體的效能,發現程式裡讀BMP圖檔時是使用SHLoadImageFile,試著去檢查一下執行的時間,居然需要用到1秒左右,這可不得了,如果讀取很多的話,那不就要load到天荒地老嗎,所以去找了一下是否有更快的讀取方式,所以就找到IImage了,改了一下,讀取時間竟只要0.5秒!太神奇了。

基本上SHLoadImageFile其實也是使用IImage的,不過為何會多出那0.5秒,由於沒辦法看到實作,所以也沒辦法知道,anyway,來看看如何使用吧。

SHLoadImageFile很簡單,只要加上檔案路徑就可以使用了,此外,它也有讀取Resource的版本SHLoadImageResource:
#include <aygshell.h>    // SHLoadImageFile
HBITMAP bmp = SHLoadImageFile("C:\\test.bmp");    // 傳回HBITMAP
是不是非常簡單啊XD,不過效能就點點點了;至於IImage的話,會比較麻煩些了,初始化的步驟要自己來:
#include <imaging.h>
#include <initguid.h>
#include <imgguids.h>

IImagingFactory *pImgFactory = NULL;
IImage *pImage = NULL;

CoInitializeEx(NULL, COINIT_MULTITHREADED);
SUCCEEDED(CoCreateInstance (CLSID_ImagingFactory, 
                            NULL, 
                            CLSCTX_INPROC_SERVER, 
                            IID_IImagingFactory, 
                            (void **)&pImgFactory));
SUCCEEDED(pImgFactory->CreateImageFromFile(strBmpPath.c_str(), &pImage));

// 在此我把圖檔貼到記憶體區,然後最後再輸出
ImageInfo bmpinfo;
pImage->GetImageInfo(&bmpinfo);
// 建立Bitmap供貼圖
HBITMAP hBitmap = ::CreateCompatibleBitmap(obj.m_hMemDC, bmpinfo.Width, bmpinfo.Height);
HDC newDC = ::CreateCompatibleDC(obj.m_hMemDC);
HBITMAP hOldBitmap = reinterpret_cast<HBITMAP>(::SelectObject(newDC, reinterpret_cast<HGDIOBJ>(hBitmap)));

RECT rc = { 0, 0, bmpinfo.Width, bmpinfo.Height };
pImage->Draw(newDC, &rc, NULL);    // 貼在newDC上

// 在貼到主視圖上(hDC)
::BitBlt(hDC, pt.x, pt.y, bmpinfo.Width , bmpinfo.Height, newDC, 0, 0, SRCCOPY);

// 貼完記得要Delete
::SelectObject(newDC, reinterpret_cast<HGDIOBJ>(hOldBitmap));
::DeleteObject(hBitmap);
::DeleteDC(newDC);
if (pImage != NULL)
{
    pImage->Release();
    pImage = NULL;
}

if (pImgFactory != NULL)
{
    pImgFactory->Release();
    pImgFactory = NULL;
}

CoUninitialize();    // 必備
步驟是多了點,不過效能有好些的話,都是值得的啦!

0 意見:

張貼留言