首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

MFC 顯示 JPG/GIF 圖片:利用 IPicture COM 介面免編寫解碼器

     編輯:關於C語言

核心思路

Windows 系統內建 OleAut32.dll 提供 IPicture COM 介面,支援 BMP、JPG、GIF、TIFF、PNG (IE 安裝後) 等格式解碼。MFC/C++ 可直接使用,無需第三方庫 (如 libjpeg、giflib)。

IPicture 關鍵方法

完整載入並繪製流程


#include  // IPicture 定義
#pragma comment(lib, "olepro32.lib") // OleLoadPicture

void DrawPicture(CDC* pDC, LPCTSTR szFile, int x, int y, int w, int h) {
    // 1. 建立檔案 Stream
    LPSTREAM pStream = NULL;
    HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
    if (FAILED(hr)) return;

    CFile file;
    if (!file.Open(szFile, CFile::modeRead | CFile::shareDenyNone)) { pStream->Release(); return; }
    DWORD dwSize = (DWORD)file.GetLength();
    HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwSize);
    LPVOID pData = GlobalLock(hGlobal);
    file.Read(pData, dwSize);
    file.Close();
    GlobalUnlock(hGlobal);

    hr = pStream->Write(pData, dwSize, NULL);
    GlobalFree(hGlobal);
    if (FAILED(hr)) { pStream->Release(); return; }

    LARGE_INTEGER li = { 0 };
    pStream->Seek(li, STREAM_SEEK_SET, NULL);

    // 2. 載入 IPicture
    IPicture* pPicture = NULL;
    hr = OleLoadPicture(pStream, dwSize, TRUE, IID_IPicture, (LPVOID*)&pPicture);
    pStream->Release();
    if (FAILED(hr) || !pPicture) return;

    // 3. 繪製 (Render 參數為 HiMetric 單位)
    long hmWidth, hmHeight;
    pPicture->get_Width(&hmWidth);
    pPicture->get_Height(&hmHeight);

    // 轉換 HiMetric → 像素 (依目標 DC 解析度)
    int nWidth = MulDiv(hmWidth, pDC->GetDeviceCaps(LOGPIXELSX), 2540);
    int nHeight = MulDiv(hmHeight, pDC->GetDeviceCaps(LOGPIXELSY), 2540);

    // 目標矩形 (像素)
    RECT rcDest = { x, y, x + (w>0?w:nWidth), y + (h>0?h:nHeight) };
    // 來源矩形 (HiMetric, 整張圖)
    RECT rcSrc = { 0, 0, hmWidth, hmHeight };

    hr = pPicture->Render(pDC->m_hDC, 
        rcDest.left, rcDest.top, rcDest.right - rcDest.left, rcDest.bottom - rcDest.top,
        rcSrc.left, rcSrc.top, rcSrc.right - rcSrc.left, rcSrc.bottom - rcSrc.top, NULL);

    pPicture->Release();
}

MFC 封裝類別 CPicture (參考 MSDN 範例)


class CPicture {
    IPicture* m_pPicture;
public:
    CPicture() : m_pPicture(NULL) {}
    ~CPicture() { if (m_pPicture) m_pPicture->Release(); }

    BOOL Load(LPCTSTR szFile) {
        // ... 同上 CreateStreamOnHGlobal + OleLoadPicture ...
    }
    BOOL LoadFromResource(UINT nResID, LPCTSTR szType = _T("JPG")) {
        // 從資源載入:FindResource/LoadResource/LockResource → CreateStreamOnHGlobal
    }
    void Render(CDC* pDC, CRect rectDest, CRect rectSrc = CRect(0,0,0,0)) {
        if (!m_pPicture) return;
        long hmW, hmH; m_pPicture->get_Width(&hmW); m_pPicture->get_Height(&hmH);
        RECT rcSrc = { 0, 0, hmW, hmH };
        if (!rectSrc.IsRectEmpty()) rcSrc = rectSrc;
        m_pPicture->Render(pDC->m_hDC, rectDest.left, rectDest.top, rectDest.Width(), rectDest.Height(),
            rcSrc.left, rcSrc.top, rcSrc.right, rcSrc.bottom, NULL);
    }
    CSize GetSizeInPixels(CDC* pDC) {
        long hmW, hmH; m_pPicture->get_Width(&hmW); m_pPicture->get_Height(&hmH);
        return CSize(MulDiv(hmW, pDC->GetDeviceCaps(LOGPIXELSX), 2540),
                     MulDiv(hmH, pDC->GetDeviceCaps(LOGPIXELSY), 2540));
    }
};

優缺點分析

方法用途
get_Handle取得 GDI 位圖控制代碼 (HBITMAP 或 HPALETTE)
get_hPal取得調色盤控制代碼
get_Type圖片類型 (1=Bitmap, 2=Metafile, 3=Icon)
get_Width/get_Height尺寸 (HiMetric 單位, 0.01 mm),需轉換像素
Render直接繪製到目標 DC,支援縮放、裁切
Load/SaveAsFile從 Stream 載入/儲存
優點缺點
零依賴,系統內建功能有限:無法存取像素資料、無法編碼寫入、無動畫 GIF 支援 (僅第一幀)
支援常見格式 (JPG/GIF/PNG/BMP/TIFF/ICO/WMF/EMF)依賴 IE/系統版本,舊系統可能不支援 PNG
Render 直接繪製,支援縮放/裁切大圖載入較慢 (全解碼至記憶體)
可從資源/檔案/Stream/URL 載入多執行緒下需注意 COM 單元模型 (STA)

現代替代方案

  • GDI+ (Gdiplus::Image): 系統內建 (WinXP+),功能更強 (像素存取、編碼、Metafile、動畫 GIF)。
  • WIC (Windows Imaging Component): Win7+ 系統級影像編解碼架構,高效能、可擴充格式。
  • 第三方庫: stb_image (單檔案)、OpenCV、FreeImage、CxImage — 功能最完整、跨平台。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved