當前位置:編程學習大全網 - 編程語言 - 如何在vc中實現jpeg文件的顯示和exif的讀取?(代碼)

如何在vc中實現jpeg文件的顯示和exif的讀取?(代碼)

摘要:本文講述了在Visual C++ 6.0下顯示JPEG、GIF等格式標準的圖像的壹種實現起來比較簡便的方法,對實現過程作有詳細的說明。

關鍵字:圖像、JPEG、GIF、Microsoft Visual C++ 6.0

壹、 引言

JPEG圖像壓縮標準隨然是壹種有損圖像壓縮標準,但由於人眼視覺的不敏感,經壓縮後的畫質基本沒有發生變化,很快便以較高的壓縮率得到了廣泛的認可。GIF格式雖然僅支持256色但它對於顏色較少的圖像有著很高的壓縮率,甚至超過JPEG標準,也得到了廣泛的認同。但作為眾多程序員的壹個重要的開發工具--Microsoft Visual C++ 6.0的MFC庫卻僅對沒有經過任何壓縮的BMP位圖文件有著良好的支持,可以讀取、顯示、存儲甚至在內存中創建壹塊內存位圖。由於BMP格式的圖像沒有經過任何的壓縮,不論是作為程序的外部文件,還是作為程序的內部資源都要占據大量的空間,尤其是後者會大大增加可執行文件的長度。可以看出,如果能用經過壓縮、具有較好的壓縮率的JPEG或GIF格式的圖像來取代BMP文件在VC中的應用,無疑還是很有吸引力的。

二、 設計思路

雖然有壹些操作、處理JPEG、GIF等其他格式圖像的Active X控件,但總的來說使用起來並不太方便,筆者經過實驗摸索,總結出了壹種借助於COM接口的OLE方法來實現上述功能的壹種簡便方法,現介紹如下以饗廣大讀者:

下面我們要使用IPicture 的COM接口,有必要對該圖像接口做些了解:該接口主要管理圖像對象及其屬性,圖像對象為 位圖、圖標和圖元等提供壹種與語言無關的抽象。和標準的字體對象壹樣,系統也提供了對圖像對象的標準實現。其主要的接口是IPicture和IPictureDisp,後者是由IDispatch接口派生以便通過自動化對圖像的屬性進行訪問。圖像對象也支持外部接口IPropertyNotifySink,以便用戶能在圖像屬性發生改變時作出決定。圖像對象也支持IPersistStream接口,所以它能從壹個IStream接口的實例對象保存、裝載自己,而IStream接口也支持對流對象的數據讀寫。

我們可以用函數OleLoadPicture從包含有圖像數據的流中裝載圖像。該函數簡化了基於流的圖像對象的創建過程,可以創建壹個新的圖像對象並且用流中的內容對它進行初始化。其函數原型為:

STDAPI OleLoadPicture( IStream * pStream, //指向包含有圖像數據的流的指針

LONG lSize, //從流中讀取的字節數

BOOL fRunmode, //圖像屬性對應的初值

REFIID riid, //涉及到的接口標識,描述要返回的接口指針的類型

VOID ppvObj // 在rrid中用到的接口指針變量的地址) ;

三、 具體的實現

在顯示圖像之前,首先要獲取到圖像文件的存放路徑,這裏采用標準的文件打開對話框來選取圖像文件,文件名存放在CString 型的變量m_sPath中:

CFileDialog dlg(TRUE,"jpg","*.jpg",

OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,

"JPEG文件(*.jpg)|*.jpg|GIF文件(*.gif)|*.gif||",NULL);

if(dlg.DoModal()==IDOK)

{

m_sPath=dlg.GetPathName();

Invalidate();

}

為簡單計,圖形顯示的代碼直接在視類中的OnDraw中編寫,首先打開文件並判斷文件的可用性,並把文件內容放到流接口IStream的對象pStm中:

IStream *pStm;

CFileStatus fstatus;

CFile file;

LONG cb;

……

if (file.Open(m_Path,CFile::modeRead)&&file.GetStatus(m_Path,fstatus)&& ((cb = fstatus.m_size) != -1))

{

HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb);

LPVOID pvData = NULL;

if (hGlobal != NULL)

{

if ((pvData = GlobalLock(hGlobal)) != NULL)

{

file.ReadHuge(pvData, cb);

GlobalUnlock(hGlobal);

CreateStreamOnHGlobal(hGlobal, TRUE, &pStm);

}

}

}

然後,就直接調用OleLoadPicture函數從流中裝載圖像:

IPicture *pPic;

……

OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic));

由於該函數有時會導致失敗,所以應當用SUCCEEDED宏來做壹些適當的保護工作,只有在數據裝載成功的前提下才能繼續下面的圖像顯示工作:

if(SUCCEEDED(OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic)))

{

OLE_XSIZE_HIMETRIC hmWidth;

OLE_YSIZE_HIMETRIC hmHeight;

pPic->get_Width(&hmWidth);

pPic->get_Height(&hmHeight);

double fX,fY;

……

fX = (double)pDC->GetDeviceCaps(HORZRES)*(double)hmWidth/((double)pDC->GetDeviceCaps(HORZSIZE)*100.0);

fY = (double)pDC->GetDeviceCaps(VERTRES)*(double)hmHeight/((double)pDC->GetDeviceCaps(VERTSIZE)*100.0);

if(FAILED(pPic->Render(*pDC,0,0,(DWORD)fX,(DWORD)fY,0,hmHeight,hmWidth,-hmHeight,NULL))) {

AfxMessageBox("渲染圖像失敗!");

pPic->Release();

}

else

AfxMessageBox("從流中裝載圖像失敗!");

}

其中,顯示工作主要是由IPicture接口對象的Render函數來完成的,該函數主要用來將圖片的指定部分畫到指定的設備環境的指定位置。原型如下:

HRESULT Render( HDC hdc, //渲染圖像用的設備環境句柄

long x, //在hdc上的水平坐標

long y, //在hdc上的垂直坐標

long cx, //圖像寬度

long cy, //圖像高度

OLE_XPOS_HIMETRIC xSrc, //在源圖像上的水平偏移

OLE_YPOS_HIMETRIC ySrc, //在源圖像上的垂直偏移

OLE_XSIZE_HIMETRIC cxSrc,//在源圖像上水平拷貝的數量

OLE_YSIZE_HIMETRIC cySrc,//在源圖像上垂直拷貝的數量

LPCRECT prcWBounds //指向目標圖元設備環境句柄的指針);

小結:

到此為止,通過上述代碼已經能夠在程序的客戶區內顯示JPEG、GIF等標準的圖像了,但對於有多幀圖片(即有動畫)的GIF格式的圖像,目前還只能顯示第壹幀,如要完整的顯示GIF 動畫的全過程,還需要外部Active X控件的支持。

PS:本文引至於天極網。 還有給妳推薦壹個編程者的好去處,多去“CSDN”上混,呵呵。

還有對圖片的EXIF信息讀取看下樓

這個類中構造了兩個結構MetadataDetail 和 Metadata ,前者是為了存儲EXIF中某元素信息的三種格式,起到中間轉化的作用,壹個是十六進制的索引信息,壹個是沒用處理過的信息代碼,壹個是顯示信息。後面的那個結構就是存儲壹張圖片所有EXIF信息元素的。 有兩個方法LookupEXIFValue 和 GetEXIFMetaData ,前壹個方法是處理特殊元素的對應顯示的,後者從圖片中讀取相關信息然後填充到MetaData結構中。

using System;

using System.Drawing;

using System.Drawing.Imaging;

using System.Collections;

using System.ComponentModel;

namespace Test.Com

{

/// <summary>

/// 功能:獲得圖片EXIF信息

/// 作者:Rexsp

/// 創建日期:2004-03-20

/// </summary>

public class EXIFMetaData

{

#region 構造函數

/// <summary>

/// 構造函數

/// </summary>

public EXIFMetaData()

{

}

#endregion

#region 數據轉換結構

/// <summary>

/// 轉換數據結構

/// </summary>

public struct MetadataDetail

{

public string Hex;//十六進制字符串

public string RawValueAsString;//原始值串

public string DisplayValue;//顯示值串

}

#endregion

#region EXIF元素結構

/// <summary>

/// 結構:存儲EXIF元素信息

/// </summary>

public struct Metadata

{

public MetadataDetail EquipmentMake;

public MetadataDetail CameraModel;

public MetadataDetail ExposureTime;//曝光時間

public MetadataDetail Fstop;

public MetadataDetail DatePictureTaken;

public MetadataDetail ShutterSpeed;// 快門速度

public MetadataDetail MeteringMode;//曝光模式

public MetadataDetail Flash;//閃光燈

public MetadataDetail XResolution;

public MetadataDetail YResolution;

public MetadataDetail ImageWidth;//照片寬度

public MetadataDetail ImageHeight;//照片高度

public MetadataDetail FNumber;// f值,光圈數

public MetadataDetail ExposureProg;// 曝光程序

public MetadataDetail SpectralSense;//

public MetadataDetail ISOSpeed;// ISO感光度

public MetadataDetail OECF;//

public MetadataDetail Ver;// EXIF版本

public MetadataDetail CompConfig;// 色彩設置

public MetadataDetail CompBPP;// 壓縮比率

public MetadataDetail Aperture;// 光圈值

public MetadataDetail Brightness;// 亮度值Ev

public MetadataDetail ExposureBias;// 曝光補償

public MetadataDetail MaxAperture;// 最大光圈值

public MetadataDetail SubjectDist;// 主體距離

public MetadataDetail LightSource;// 白平衡

public MetadataDetail FocalLength;// 焦距

public MetadataDetail FPXVer;// FlashPix版本

public MetadataDetail ColorSpace;// 色彩空間

public MetadataDetail Interop;//

public MetadataDetail FlashEnergy;//

public MetadataDetail SpatialFR;//

public MetadataDetail FocalXRes;//

public MetadataDetail FocalYRes;//

public MetadataDetail FocalResUnit;//

public MetadataDetail ExposureIndex;// 曝光指數

public MetadataDetail SensingMethod;// 感應方式

public MetadataDetail SceneType;//

public MetadataDetail CfaPattern;//

}

#endregion

#region 查找EXIF元素值

public string LookupEXIFValue(string Description, string Value)

{

string DescriptionValue = null;

switch(Description)

{

case "MeteringMode":

#region MeteringMode

{

switch(Value)

{

case "0":

DescriptionValue = "Unknown";break;

case "1":

DescriptionValue = "Average";break;

case "2":

DescriptionValue = "Center Weighted Average";break;

case "3":

DescriptionValue = "Spot";break;

case "4":

DescriptionValue = "Multi-spot";break;

case "5":

DescriptionValue = "Multi-segment";break;

case "6":

DescriptionValue = "Partial";break;

case "255":

DescriptionValue = "Other";break;

}

}

#endregion

break;

case "ResolutionUnit":

#region ResolutionUnit

{

switch(Value)

{

case "1":

DescriptionValue = "No Units";break;

case "2":

DescriptionValue = "Inch";break;

case "3":

DescriptionValue = "Centimeter";break;

}

}

#endregion

break;

//省略N行相似代碼

}

return DescriptionValue;

}

#endregion

#region 取得圖片的EXIF信息

public Metadata GetEXIFMetaData(string PhotoName)

{

// 創建壹個圖片的實例

System.Drawing.Image MyImage = System.Drawing.Image.FromFile(PhotoName);

// 創建壹個整型數組來存儲圖像中屬性數組的ID

int[] MyPropertyIdList = MyImage.PropertyIdList;

//創建壹個封閉圖像屬性數組的實例

PropertyItem[] MyPropertyItemList = new PropertyItem[MyPropertyIdList.Length];

//創建壹個圖像EXIT信息的實例結構對象,並且賦初值

#region 創建壹個圖像EXIT信息的實例結構對象,並且賦初值

Metadata MyMetadata = new Metadata();

MyMetadata.EquipmentMake.Hex = "10f";

MyMetadata.CameraModel.Hex = "110";

MyMetadata.DatePictureTaken.Hex = "9003";

MyMetadata.ExposureTime.Hex = "829a";

MyMetadata.Fstop.Hex = "829d";

MyMetadata.ShutterSpeed.Hex = "9201";

MyMetadata.MeteringMode.Hex = "9207";

MyMetadata.Flash.Hex = "9209";

MyMetadata.FNumber.Hex = "829d"; //

MyMetadata.ExposureProg.Hex = ""; //

MyMetadata.SpectralSense.Hex = "8824"; //

MyMetadata.ISOSpeed.Hex = "8827"; //

MyMetadata.OECF.Hex = "8828"; //

MyMetadata.Ver.Hex = "9000"; //

MyMetadata.CompConfig.Hex = "9101"; //

MyMetadata.CompBPP.Hex = "9102"; //

MyMetadata.Aperture.Hex = "9202"; //

MyMetadata.Brightness.Hex = "9203"; //

MyMetadata.ExposureBias.Hex = "9204"; //

MyMetadata.MaxAperture.Hex = "9205"; //

MyMetadata.SubjectDist.Hex = "9206"; //

MyMetadata.LightSource.Hex = "9208"; //

MyMetadata.FocalLength.Hex = "920a"; //

MyMetadata.FPXVer.Hex = "a000"; //

MyMetadata.ColorSpace.Hex = "a001"; //

MyMetadata.FocalXRes.Hex = "a20e"; //

MyMetadata.FocalYRes.Hex = "a20f"; //

MyMetadata.FocalResUnit.Hex = "a210"; //

MyMetadata.ExposureIndex.Hex = "a215"; //

MyMetadata.SensingMethod.Hex = "a217"; //

MyMetadata.SceneType.Hex = "a301";

MyMetadata.CfaPattern.Hex = "a302";

#endregion

// ASCII編碼

System.Text.ASCIIEncoding Value = new System.Text.ASCIIEncoding();

int index = 0;

int MyPropertyIdListCount=MyPropertyIdList.Length;

if(MyPropertyIdListCount!=0)

{

foreach (int MyPropertyId in MyPropertyIdList)

{

string hexVal = "";

MyPropertyItemList[index] = MyImage.GetPropertyItem(MyPropertyId);

#region 初始化各屬性值

string myPropertyIdString=MyImage.GetPropertyItem(MyPropertyId).Id.ToString("x");

switch(myPropertyIdString)

{

case "10f":

{

MyMetadata.EquipmentMake.RawValueAsString =BitConverter.ToString(MyImage.GetPropertyItem (MyPropertyId).Value);

MyMetadata.EquipmentMake.DisplayValue = Value.GetString(MyPropertyItemList[index].Value);

break;

}

case "110":

{

MyMetadata.CameraModel.RawValueAsString =BitConverter.ToString(MyImage.GetPropertyItem(MyPropertyId).Value);

MyMetadata.CameraModel.DisplayValue =Value.GetString(MyPropertyItemList[index].Value);

break;

}

case "9003":

{

MyMetadata.DatePictureTaken.RawValueAsString =BitConverter.ToString(MyImage.GetPropertyItem(MyPropertyId).Value);

MyMetadata.DatePictureTaken.DisplayValue =Value.GetString(MyPropertyItemList[index].Value);

break;

}

//省略N行相似代碼

}

#endregion

index++;

}

}

MyMetadata.XResolution.DisplayValue = MyImage.HorizontalResolution.ToString();

MyMetadata.YResolution.DisplayValue = MyImage.VerticalResolution.ToString();

MyMetadata.ImageHeight.DisplayValue = MyImage.Height.ToString();

MyMetadata.ImageWidth.DisplayValue = MyImage.Width.ToString();

MyImage.Dispose();

return MyMetadata;

}

#endregion

}

}

然後就是個調用的問題,有了這個類,我如何讀取圖片的EXIF信息呢?代碼如下:

EXIFMetaData em = new EXIFMetaData();

string filePath=Server.MapPath("Test.jpg");//這裏可以動態傳遞圖片路徑的

EXIFMetaData.Metadata m = em.GetEXIFMetaData(filePath);//這裏就是調用,傳圖片絕對路徑

string exif = m.Ver.DisplayValue;

string camera = m.CameraModel.DisplayValue;

string model = m.CameraModel.DisplayValue;

string aperture = m.Aperture.DisplayValue;

string shutter = m.ShutterSpeed.DisplayValue;

string sensitive = m.ExposureIndex.DisplayValue;

此代碼經過測試,功能正常。

  • 上一篇:全國大學生參加的競賽有哪些?
  • 下一篇:用4,6,7這三個數組成壹個三位數,最大的數是
  • copyright 2024編程學習大全網