• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • VC實現多格式圖像的轉換

    發表于:2007-07-14來源:作者:點擊數: 標簽:
    ◆ 周鳴揚 (healthboy@163 .net ) 色彩鮮艷漂亮的高品質圖像,一個個形象生動的Windows圖標,高速運動、活靈活現的三維動畫,這些無一不顯示出程序設計者的藝術才華。在程序設計中,圖像處理已經成為每個 程序員 的必修課。 在VC中編程顯示一幅位圖,下列步
    ◆ 周鳴揚 (healthboy@163.net)

    色彩鮮艷漂亮的高品質圖像,一個個形象生動的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)?!绑w驗”過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+聲明和初始化及銷毀進行代碼編制,具體代碼如下:

    #include “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+的應用遠不止此。

    結束語

    如果對本程序進行些改進,還可以編制出功能更加強大的圖像處理程序。本文中所提到的程序,在筆者的主頁“國稅之家”(http://nationaltax.home.chinaren.com)的“個人世界”中可以下載到。有關GDI+編程的幫助信息,大家可以到微軟的MSDN網站去查閱。

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>