日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

10、wpf显示图片方式一: Image控件

發布時間:2023/12/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 10、wpf显示图片方式一: Image控件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:整理下wpf image控件顯示圖片的方式,分為本地圖片和內存圖片(來自于網絡交互中的圖片)

一、Image

命名空間:System.Windows.Controls

程序集:PresentationFramework.dll

表示用于顯示圖像的控件,這個圖像一般就是指我們本地文件存儲的照片或來自于網絡請求中的照片資源。

[System.Windows.Localizability(System.Windows.LocalizationCategory.None, Readability=System.Windows.Readability.Unreadable)] public class Image : System.Windows.FrameworkElement, System.Windows.Markup.IUriContext

繼承?Object?→?DispatcherObject?→?DependencyObject?→?Visual?→?UIElement?→

FrameworkElement?→?Image

Image類可用于加載以下圖像類型: .bmp、.gif、.ico、.jpg、.png、wdp 和 tiff。

二、 Image賦值-本地圖像資源

Image賦值方式有多種,這里分為本地圖像資源賦值和內存(網絡請求圖像資源)

查看Image的屬性可以看到,有一個Source屬性,其類型為ImageSource類型

//// 摘要:// 獲取或設置圖像的 System.Windows.Media.ImageSource。//// 返回結果:// 所繪制圖像的源。 默認值為 null。public ImageSource Source { get; set; }

導航到ImageSource類,可以看到他在Media名下,不是在Drawing名下,說明是一種多媒體文件格式。因為是一個抽象類,我們不能直接使用他,需要使用他的實現類。同時他有個ToString方法,所以在XAML中經常為Image的Source屬性附上一個string(本地圖片地址)就可以。

2.1 XAML引用資源

<Grid><Grid.RowDefinitions><RowDefinition Height="*"/><RowDefinition Height="*"/> </Grid.RowDefinitions> <Image Source="{Binding ImgPath}"/><Image Grid.Row="1" Source="pack://application:,,,/Resource/ButtonClick_16x.png"/></Grid>//踩坑:Source這里使用的相對位置,但是如果不加"pack://application:,,,"就不能顯示成功,具體的參考這篇博客:https://www.cnblogs.com/g120/p/4688101.html //code-behindpublic string ImgPath { get; set; }public MainWindowViewModel(){ImgPath = "pack://application:,,,/Resource/Brush_16x.png";}

2.2 ImageSource方式--用代碼引用資源

前面說了,ImageSource是一個抽象類,不能直接使用他,而是使用他的繼承類來代替,查閱MSDN如下:

?BitmapSource(也是個抽象類)派生自ImageSource,就用它的子類BitmapImage來實現了

//code-behind image.Source = new BitmapImage(new Uri("imgPath", UriKind.Absolute));

三、Image賦值-內存(網絡請求資源)

當圖像來自于攝像頭或者屏幕截圖或者網頁圖片時,就需要在內存中進行操作。WPF的Image控件的Source屬性的類型為ImageSource,只要是繼承自ImageSource的對象都可以賦值給Source屬性,前面講過BitmapImage繼承自BitmapSource,而BitmapSource又繼承自ImageSource,因此為了能夠將內存中的Bitmap位圖顯示在Image控件中,需要將Bitmap轉換為ImageSource類型。

轉換方式有多種,筆者這里將查詢到的三種方式做下介紹。

3.1 Bitmap類定義

命名空間:System.Drawing

程序集:System.Drawing.dll

封裝 GDI+ 位圖,此位圖由圖形圖像及其屬性的像素數據組成。?Bitmap?是用于處理由像素數據定義的圖像的對象。

[System.Runtime.InteropServices.ComVisible(true)] [System.Serializable] public sealed class Bitmap : System.Drawing.Image

繼承 Object→MarshalByRefObject→Image→Bitmap

屬性?ComVisibleAttribute?SerializableAttribute

3.2?WriteableBitmap

這種方式不安全,有可能會把內存搞炸,慎用。個人理解是將bitmap中數據導入到WriteableBitmap中,然后再賦值給Image使用。

?

因為是從bitmap導數據到WriteableBitmap中,因此需要創建一個與Bitmap大小相同,像素格式兼容的WriteableBitmap。

WriteableBitmap wb = new WriteableBitmap(bitmap.Width, bitmap.Height, 0, 0, System.Windows.Media.PixelFormats.Bgra32, null);

?然后調用Bitmap的LockBits獲取其內部的圖像數據,通過WritePixels的方式寫入WriteableBitmap,這樣即完成了轉換。

var data = bitmap.LockBits(new System.Drawing.Rectangle(new System.Drawing.Point(0, 0), bitmap.Size), System.Drawing.Imaging.ImageLockMode.ReadOnly, src.PixelFormat);wb.WritePixels(new Int32Rect(srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height), data.Scan0, data.Height * data.Stride, data.Stride, destinationX, destinationY); bitmap.UnlockBits(data); //將Bitmap 轉換成WriteableBitmap public static WriteableBitmap BitmapToWriteableBitmap(System.Drawing.Bitmap src) {var wb = CreateCompatibleWriteableBitmap(src);System.Drawing.Imaging.PixelFormat format = src.PixelFormat;if (wb == null){wb = new WriteableBitmap(src.Width, src.Height, 0, 0, System.Windows.Media.PixelFormats.Bgra32, null);format = System.Drawing.Imaging.PixelFormat.Format32bppArgb;}BitmapCopyToWriteableBitmap(src, wb, new System.Drawing.Rectangle(0, 0, src.Width, src.Height), 0, 0, format);return wb; } //創建尺寸和格式與Bitmap兼容的WriteableBitmap public static WriteableBitmap CreateCompatibleWriteableBitmap(System.Drawing.Bitmap src) {System.Windows.Media.PixelFormat format; switch (src.PixelFormat){case System.Drawing.Imaging.PixelFormat.Format16bppRgb555:format = System.Windows.Media.PixelFormats.Bgr555;break;case System.Drawing.Imaging.PixelFormat.Format16bppRgb565:format = System.Windows.Media.PixelFormats.Bgr565;break;case System.Drawing.Imaging.PixelFormat.Format24bppRgb:format = System.Windows.Media.PixelFormats.Bgr24;break;case System.Drawing.Imaging.PixelFormat.Format32bppRgb:format = System.Windows.Media.PixelFormats.Bgr32;break; case System.Drawing.Imaging.PixelFormat.Format32bppPArgb:format = System.Windows.Media.PixelFormats.Pbgra32;break; case System.Drawing.Imaging.PixelFormat.Format32bppArgb:format = System.Windows.Media.PixelFormats.Bgra32;break;default:return null;}return new WriteableBitmap(src.Width, src.Height, 0, 0, format, null); } //將Bitmap數據寫入WriteableBitmap中 public static void BitmapCopyToWriteableBitmap(System.Drawing.Bitmap src, WriteableBitmap dst, System.Drawing.Rectangle srcRect, int destinationX, int destinationY, System.Drawing.Imaging.PixelFormat srcPixelFormat) {var data = src.LockBits(new System.Drawing.Rectangle(new System.Drawing.Point(0, 0), src.Size), System.Drawing.Imaging.ImageLockMode.ReadOnly, srcPixelFormat);dst.WritePixels(new Int32Rect(srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height), data.Scan0, data.Height * data.Stride, data.Stride, destinationX, destinationY);src.UnlockBits(data); }

3.3?Imaging.CreateBitmapSourceFromHBitmap

[DllImport("gdi32.dll", SetLastError = true)]private static extern bool DeleteObject(IntPtr hObject);/// <summary>/// 從bitmap轉換成ImageSource/// </summary>/// <param name="icon"></param>/// <returns></returns>public static ImageSource ChangeBitmapToImageSource(Bitmap bitmap){//Bitmap bitmap = icon.ToBitmap();IntPtr hBitmap = bitmap.GetHbitmap();ImageSource wpfBitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBitmap,IntPtr.Zero,Int32Rect.Empty,BitmapSizeOptions.FromEmptyOptions());if (!DeleteObject(hBitmap)){throw new System.ComponentModel.Win32Exception();}//一定要卸載IntPtr,否則內存泄漏很快就沒有內存了。網上有人說這個方法有時不能卸載掉,我短時間測試是能夠及時卸載掉內存的。需要說明的是:DeleteObject()方法不會影響imgSource和bmp中的數據,也就是DeleteObject()執行過后,imgSource和bmp中的圖像數據依然完整地存在。為了能使用DeleteObject方法,需要聲明來自于gdi32的外部函數 [DllImport("gdi32")]static extern int DeleteObject(IntPtr o),參考MSDN說明https://msdn.microsoft.com/zh-tw/library/1dz311e4(v=vs.80).aspx?cs-save-lang=1&cs-return wpfBitmap;}

3.4?MemoryStream

先將Bitmap數據Save到Memory Stream中,然后再用MemoryStream將其轉換為字節數組,再利用MemoryStream來賦值給BitmapImage的StreamSource屬性,從而間接將Bitmap對象轉換為BitmapImage對象

private BitmapImage BitmapToBitmapImage(System.Drawing.Bitmap bitmap) {Bitmap b = new Bitmap(bCode);MemoryStream ms = new MemoryStream();b.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);byte[] bytes = ms.GetBuffer(); //byte[] bytes= ms.ToArray(); 這兩句都可以ms.Close();//Convert it to BitmapImageBitmapImage image = new BitmapImage();image.BeginInit();image.StreamSource = new MemoryStream(bytes);image.EndInit();return image ; }

引用文章:C# wpf Bitmap轉換成WriteableBitmap(BitmapSource)的方法_Alfred-N的博客-CSDN博客

使用不安全代碼將 Bitmap 位圖轉為 WPF 的 ImageSource 以獲得高性能和持續小的內存占用 - walterlvWPF 使用不安全代碼快速從數組轉 WriteableBitmap

?

總結

以上是生活随笔為你收集整理的10、wpf显示图片方式一: Image控件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。