在VC 中使用GDI+

來源:互聯網
上載者:User

在 標頭檔 stdafx.h 添加如下的代碼
#define ULONG_PTR unsigned long
#include <Gdiplus.h>
using namespace Gdiplus;
在 CWinApp 派生出來的 你自己的 C×App 的標頭檔 添加
ULONG_PTRgdiplusToken;
在 BOOL C×App::InitInstance() 中添加
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
就可以了 編譯了 ,當然需要添加 包含檔案的路徑

--------------------------------------------------------------------------------

要用到GdiPlus.lib
#include "GdiPlus.h"

--------------------------------------------------------------------------------

http://www.vckbase.com/document/viewdoc/?id=470

最好將#include "GdiPlus.h"放到Stdafx.h中。這樣哪裡都可以用了

--------------------------------------------------------------------------------

色彩鮮豔漂亮的高品質映像,一個個形象生動的Windows表徵圖,高速運動、活靈活現的三維動畫,這些無一不顯示出程式設計者的藝術才華。在程式設計中,影像處理已經成為每個程式員的必修課。

在VC中編程顯示一幅位元影像,下列步驟是不可缺少的: 裝入位元影像、獲得位元影像的大小資訊、啟用裝置環境、位傳輸等,所需的程式碼一般比較冗長而且複雜。如果想將裝入的位元影像另存新檔其他格式的影像檔,代碼就更長了。這一切都是因為GDI本身的局限性造成的。

GDI+技術

隨著Windows 2000的推出,上述情況有了極大的改觀: 程式員不必瞭解每種映像格式的具體含義,照樣可以寫出多格式映像瀏覽或轉換程式,這一切全都依賴於Windows 2000及後繼版中所使用的GDI+技術。

和傳統的GDI不同,GDI+中引入了對COM(元件物件模型)技術的支援,通過COM技術,GDI+簡化了對影像檔的訪問(開啟、儲存)。它是通過調用COM組件來實現的,GDI+扮演的只是指揮者,而非操作員。對於影像檔,GDI+所關心的不是影像檔的檔案頭資訊,不論要開啟的檔案格式是什麼類型,GDI+首先要做的是在註冊表中查看該映像格式的編碼(或解碼)資訊是否已經註冊(HKEY_CLASSES_ROOT/MIME/Database/Content Type)。如果已經註冊,就通過該編碼資訊調用COM組件,就這麼簡單。這種技術早就在微軟的其他軟體中使用了(如IE)。“體驗”過Nimda病毒的朋友可能對“audio/wav”這段代碼並不陌生,Nimda就是靠它來偽裝自己的:讓IE認為附件是WAV檔案而自動開啟可執行程式,這其實也是IE 使用COM技術的一個突出表現。

配合GDI+的推出,微軟也同時發布了相應的SDK,如果已經安裝了最新的Microsoft PlatForm SDK或已經開始使用VS.NET,GDI+的SDK就已經在系統中了。如果沒有的話,可以到http: //noner.top263.net/progtool上去下載GDI+的標頭檔和庫檔案。有了GDI+之後,只需簡單地建立一個繪圖物件(Graphics object),然後直接調用該對象的方法(methods)進行繪圖即可。繪圖物件是GDI+中的核心,正如DC之於GDI那樣。繪圖物件和DC有許多相似的地方,在使用上遵循著相同的使用規則,但是兩者在本質上已經有很大的區別。一個是基於控制代碼的GDI,一個是基於元件物件模型的GDI+。使用 GDI+的SDK編程,必須按照下面的規範來進行:使用GDI+的命名空間(namespace Gdiplus),在使用GDI+函數時必須進行GDI+的初始化,使用完畢要銷毀GDI+,這些規範在下面所列的程式中有詳細的說明。

訪問註冊表編碼資訊

上面說到GDI+是通過在註冊表中查看編碼資訊來訪問影像檔的,在GDI+的SDK中,編碼資訊是儲存在 ImageCodecInfo類中的,在這個類中,有編碼的CLSID(COM組件的GUID標識碼)、編碼方式描述等。對於GDI,在註冊表中訪問編碼資訊通常使用以下兩個函數來實現:

1. 查看系統中可用的映像編碼資訊(數量及大小)

Status GetImageEncodersSize(

UINT* numEncoders,

//儲存編碼器數量的地址

UINT* size //儲存編碼資訊所需記憶體大小

);

2. 得到所有的編碼資訊

Status GetImageEncoders(

UINT numEncoders,//可用編碼器數量

UINT size,//儲存編碼器資訊所需記憶體(由ImageCodecInfo類組成的數組的大小)

ImageCodecInfo* encoders//編碼器資訊指標

);

在GetImageEncoders函數中,參數numEncoders和 size都是由GetImageEncodersSize返回的。下面的代碼在註冊表中尋找具體格式映像的編碼方式:

int GetImageCLSID(const WCHAR* format, CLSID* pCLSID)

{ //得到格式為format的影像檔的編碼值,訪問該格式映像的COM組件的GUID值儲存在pCLSID中

UINT num = 0;

UINT size = 0;

ImageCodecInfo* pImageCodecInfo = NULL;

GetImageEncodersSize(&num, &size);

if(size == 0)

return FALSE; // 編碼資訊不可用

//分配記憶體

pImageCodecInfo = (ImageCodecInfo*)(malloc(size));

if(pImageCodecInfo == NULL)

return FALSE; // 分配失敗

//獲得系統中可用的編碼方式的所有資訊

GetImageEncoders(num, size, pImageCodecInfo);

//在可用編碼資訊中尋找format格式是否被支援

for(UINT i = 0; i < num; ++i)

{ //MimeType:編碼方式的具體描述

if( wcscmp(pImageCodecInfo[i]

.MimeType, format) == 0 )

{

*pCLSID = pImageCodecInfo[i]

.Clsid;

free(pImageCodecInfo);

return TRUE;

}

}

free(pImageCodecInfo);

return FALSE;

}

實現多格式的映像瀏覽和轉換

有了前面的知識,實現多格式的映像的瀏覽與轉換就不是什麼難事了。

1.在VC中建立一個SDI項目ImageShow,對GDI+聲明和初始化及銷毀進行代碼編製,具體代碼如下:

#i nclude “Gdiplus.h”

using namespace Gdiplus;

CImageShowView::CImageShowView()

{

//初始化GDI+

GdiplusStartupInput gdiplusStartupInput;

ULONG_PTR gdiplusToken;

GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

}

CImageShowView::~CImageShowView()

{

//銷毀GDI+

ULONG_PTR gdiplusToken;

GdiplusShutdown(gdiplusToken);

}

2. 通過類嚮導(Class Wizard),重載[檔案] 功能表中的“開啟”和“另存新檔”兩項。為了編程的簡單,本程式只將當前開啟的影像檔直接存為BMP檔案(實際上儲存為其他格式的檔案也很簡單,只不過是對檔案名稱進行分析而已)。另外,為了在開啟和儲存檔案時進行檔案名稱的傳遞,還應在CImageShowView類中加入一全域變數“CString strOpenFileName”。“開啟”和“另存新檔”兩菜單的對應代碼如下:

WCHAR* ToWChar(char * str)

{

//在GDI+中,有關字元的參數類型全部都是WCHAR類型

// 該函數是將傳統字串進行轉換

static WCHAR buffer[1024];

wcsset(buffer,0);

MultiByteToWideChar(CP_ACP,0,str,strlen(str),buffer,1024);

return buffer;

}

void CImageShowView::OnFileOpen()

{

// 本程式能夠開啟各類常見格式的影像檔 static char szFilter[]=“常見格式影像檔(*.*)|*.*|”;

CFileDialog dlgChoseImage(1,NULL,NULL,NULL,szFilter);

if(dlgChoseImage.DoModal()==IDOK)

{

strOpenFileName=dlgChoseImage

.GetPathName();

//開啟檔案後立即在視窗中顯示(重繪客戶視窗)

this->Invalidate();

}

}

void CImageShowView::OnFileSaveAs()

{

if(strOpenFileName.IsEmpty())

{

AfxMessageBox(“當前沒有開啟影像檔,不能進行儲存!”);

return;

}

//建立繪圖物件

Graphics graphics(GetDC()->m_hDC);

// 裝入當前已經開啟的影像檔

Image image(ToWChar(strOpenFileName.GetBuffer(strOpenFileName.GetLength())));

CString strFileSave;

//將其他格式的映像全部另存新檔BMP檔案

static char szFilter[]=“位元影像(*.BMP)|*.BMP|”;

CFileDialog dlgChoseImage(0,“BMP”,NULL,NULL,szFilter);

if(dlgChoseImage.DoModal()==IDOK)

{

strFileSave=dlgChoseImage.GetPathName();

CLSID clsid;

if(GetImageCLSID(L“image/bmp”,&clsid))

{

image.Save(ToWChar(strFileSave.GetBuffer(strFileSave.GetLength())), &clsid, NULL);

//將儲存後的映像進行顯示

strOpenFileName=strFileSave;

this->Invalidate();

}

}

}

3.為了瀏覽映像轉換前後的效果,還應該在視窗中分別繪製轉換前後的映像,這需要在OnDraw函數中添加繪製代碼,如下所示:

void CImageShowView::OnDraw(CDC* pDC)

{

CImageShowDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

//如果沒有選擇顯示影像檔,則不用重繪

if(strOpenFileName.IsEmpty())

return;

//顯示當前開啟的影像檔的全名

this->GetParent()->SetWindowText(strOpenFileName);

//建立映像對象

Graphics graphics(pDC->m_hDC);

//裝入圖形檔案

Image image(ToWChar(strOpenFileName.GetBuffer(strOpenFileName.GetLength())));

Point destPoints[3] =

{

Point(0, 0),

Point(image.GetWidth(), 0),

Point(0, image.GetHeight())

};

Point* pdestPoints = destPoints;

//在指定地區pdestPoints顯示映像

graphics.DrawImage(&image, pdestPoints, 3);

}

在編譯上面的程式之前,應該將Gdiplus.lib檔案連編到項目中去,否則將會出現“LINK 2001”編譯錯誤。上述程式在Visual Studio 6.0、Windows 2000/XP下調試通過,它能夠顯示或轉換的映像格式有BMP、GIF、JPEG、Exif、PNG、TIFF、ICON、WMF、EMF等等。需要說明的是,本文只就GDI+編程的基本原理進行了闡述,事實上,GDI+的應用遠不止此。

本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/sky04/archive/2010/04/30/5541891.aspx

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.