把圖片改成jpg格式,在WPF里面顯示DIB圖片格式的圖片

 2023-10-15 阅读 25 评论 0

摘要:前幾天寫程序需要將DIB(設備無關位圖)格式的圖片在WPF 程序中顯示出來,在網上查了一些資料和代碼,記錄下來以便以后參考。 設備有關位圖主要是顯卡在顯存中保存的圖片格式,顯卡就是從顯存里面將要顯示的圖片數據直接打印到顯示器上࿰

前幾天寫程序需要將DIB(設備無關位圖)格式的圖片在WPF 程序中顯示出來,在網上查了一些資料和代碼,記錄下來以便以后參考。

設備有關位圖主要是顯卡在顯存中保存的圖片格式,顯卡就是從顯存里面將要顯示的圖片數據直接打印到顯示器上,這樣不僅節省了系統內存的空間,還大大節省了從內存把圖片數據搬到顯存的時間因為顯卡芯片可以實現一些指令,直接操作顯存中的圖片。所以設備有關位圖的格式不是固定的,是由顯卡制造商自由決定的,這也就意味著我們沒有辦法直接操作DDB格式圖片的每一個像素。

如果保存在硬盤的圖片格式是以DDB格式保存的話,那就意味著你使用一個顯卡保存的圖片不能在使用不同型號的顯卡的機器上打開因為不同顯卡制造商使用的DDB的格式不一樣。為了解決這個問題,在很久以前,微軟的GDI系統就提供了DIB(設備無關位圖),相當于一種中間格式,在顯示DIB圖片的之前,GDI先將DIB位圖轉換成顯卡能夠理解的DDB格式當然這一系列的操作都是由顯卡的指令完成的。

WPFWinform的世界里,大家針對圖片的編程相對來說都比較舒服,因為.NET Framework提供了簡化的API幫你隱藏了這些細節,所有你需要做的就是:

WPF:

var image = new Image();

把圖片改成jpg格式。?image.Source = new BitmapImage(new Uri("some image.jpg"));

Winform:

var image = System.Drawing.Image.FromFile("some image.jpg");

?

恩,看起來很美,但問題是,因為微軟的函數庫實在是太多了,強大如.NET這種類庫也有考慮不周的時候,WPF并沒有公開的API直接從DIB格式的圖片中生成BitmapImage實例。為什么有的時候我們需要直接操作DIB格式的圖片呢?例如你需要從剪貼板里面拿一個圖片出來,而把圖片放置到剪貼板的程序有可能并不是.NET程序,而是古老的OLE程序或者Win32程序,這些老古董經常喜歡在剪貼板里面放兩個格式的圖片,一個是DIB格式的,另外一個可能是支持IDataObject的接口這個接口怎么實現又是仁者見仁,智者見智的事情。這個時候,你就發現你必須要處理DIB格式的圖片;另外一種情況就是拖拉操作,因為拖拉操作中數據源和接受數據的程序有可能不是同一個程序,例如,你從一個OLE程序里面拖拉一個圖片到WPF程序里。

根據MSDNDIB圖片的格式如下圖所示:

wpf圖片環繞、

?

下面的代碼是我從網上搜到的關于如何從DIB格式生成BitmapImage實例的代碼:

??????? private System.Drawing.Bitmap CreateBitmapFromDib(Stream dib)

??????? {

??????????? BinaryReader reader = new BinaryReader(dib);

?

??????????? int headerSize = reader.ReadInt32();

??????????? int pixelSize = (int)dib.Length - headerSize;

??????????? int fileSize = 14 + headerSize + pixelSize;

?

??????????? MemoryStream bmp = new MemoryStream(fileSize);

??????????? BinaryWriter writer = new BinaryWriter(bmp);

?

??????????? // 1. 把位圖的一些元數據寫進去,下面這幾次Write相當于填寫Win32

??????????? // BITMAPFILEHEADER結構 ???????

??????????? writer.Write((byte)'B');

??????????? writer.Write((byte)'M');

??????????? writer.Write(fileSize);

??????????? writer.Write((int)0);

??????????? writer.Write(14 + headerSize);

?

??????????? // 2. DIB位圖中的像素矩陣拷貝出來到我們指定的MemoryStream里。?

??????????? // 因為我們要從MemoryStream里面生成System.Drawing.Bitmap對象

??????????? // 然后再頗為曲折地從Bitmap對象生成WPFBitmapImage對象

??????????? dib.Position = 0;

??????????? byte[] data = new byte[(int)dib.Length];

??????????? dib.Read(data, 0, (int)dib.Length);

??????????? writer.Write(data, 0, (int)data.Length);

?

??????????? // 3. 生成Bitmap對象這個是Winform里面的Bitmap對象

??????????? bmp.Position = 0;

??????????? return new System.Drawing.Bitmap(bmp);

??????? }

?

wpf設置背景圖片、上面那一段代碼也相當于下面的C++代碼,從MFC的實例代碼里面找到的:

HDIB WINAPI ReadDIBFile(CFile& file)

{

??????????????? BITMAPFILEHEADER bmfHeader;

??????????????? UINT nBitsSize;

??????????????? HDIB hDIB;

??????????????? LPSTR pDIB;

?

??????????????? /*

??????????????? ?* get length of DIB in bytes for use when reading

??????????????? ?*/

?

??????????????? nBitsSize = (UINT)file.GetLength();

?

??????????????? /*

??????????????? ?* Go read the DIB file header and check if it's valid.

??????????????? ?*/

??????????????? if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))

??????????????????????????????? return NULL;

?

??????????????? if (bmfHeader.bfType != DIB_HEADER_MARKER)

??????????????????????????????? return NULL;

?

??????????????? /*

??????????????? ?* Allocate memory for DIB

??????????????? ?*/

??????????????? hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, (DWORD)nBitsSize);

??????????????? if (hDIB == 0)

??????????????? {

??????????????????????????????? return NULL;

??????????????? }

??????????????? pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);

?

??????????????? /*

??????????????? ?* Go read the bits.

??????????????? ?*/

??????????????? if (file.Read(pDIB, nBitsSize - sizeof(BITMAPFILEHEADER)) !=

??????????????????????????????? nBitsSize - sizeof(BITMAPFILEHEADER) )

??????????????? {

??????????????????????????????? ::GlobalUnlock((HGLOBAL) hDIB);

??????????????????????????????? ::GlobalFree((HGLOBAL) hDIB);

??????????????????????????????? return NULL;

??????????????? }

??????????????? ::GlobalUnlock((HGLOBAL) hDIB);

??????????????? return hDIB;

}

?

得到System.Drawing.Bitmap實例以后,就可以通過下面的函數來創建BitmapImage對象了:

private BitmapSource BitmapToImageSource(System.Drawing.Bitmap bitmap)

{

??? BitmapSource destination;

??? IntPtr hBitmap = bitmap.GetHbitmap();

??? BitmapSizeOptions sizeOptions = BitmapSizeOptions.FromEmptyOptions();

??? destination = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, sizeOptions);

??? destination.Freeze();

??? return destination;

}

可編輯的圖片格式??

?

?

轉載于:https://www.cnblogs.com/killmyday/archive/2010/02/19/1669346.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/2/139592.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息