前言
图片我们可能是这样加载的
1 2 3 4 5 6 7 8
| <Image Source="{Binding Pic}" Stretch="Fill"> <Image.Clip> <EllipseGeometry Center="25,25" RadiusX="25" RadiusY="25" /> </Image.Clip> </Image>
|
这种方式适合加载程序自身的图片。
但是不建议加载新生成的图片,比如截屏。
因为这样加载一方面图片的内存释放会有问题,容易导致内存泄漏,另一方面,被加载的图片就会处于占用状态,如果此时我们要处理图片比如压缩上传,就会因占用而报错。
正由另一进程使用,因此该进程无法访问此文件。
WPF列表中加载
添加一个转换器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| using System; using System.Globalization; using System.IO; using System.Windows.Data; using System.Windows.Media.Imaging;
namespace ZConverter { public class StringToImageSourceConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { string path = (string)value; if (!string.IsNullOrEmpty(path)) { return GetImage(path); } else { return null; } }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return null; }
private BitmapImage GetImage(string imagePath) { BitmapImage bi = new BitmapImage(); if (File.Exists(imagePath)) { bi.BeginInit(); bi.CacheOption = BitmapCacheOption.OnLoad; using (Stream ms = new MemoryStream(File.ReadAllBytes(imagePath))) { bi.StreamSource = ms; bi.EndInit(); bi.Freeze(); } } return bi; } } }
|
原来加载的地方改为
1 2 3 4 5 6 7 8
| <Window xmlns:cv="clr-namespace:SchoolClient.Converters"> <Window.Resources> <cv:StringToImageSourceConverter x:Key="StringToImageSourceConverter" /> </Window.Resources> <Image Source="{Binding Path=Pic, Converter={StaticResource StringToImageSourceConverter}}" Stretch="Uniform" /> </Window>
|
代码中加载
上面说的是在WPF中使用转换器来把图片加载到内存中的方式,当然我们也可以在代码中加载。
工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| using System; using System.Drawing.Imaging; using System.Drawing; using System.IO; using System.Windows.Media.Imaging;
namespace Z.Utils.Common { public class ZImageUtils { public static BitmapImage GetImage(string imagePath) { BitmapImage bi = new BitmapImage(); if (File.Exists(imagePath)) { bi.BeginInit(); bi.CacheOption = BitmapCacheOption.OnLoad; using (Stream ms = new MemoryStream(File.ReadAllBytes(imagePath))) { bi.StreamSource = ms; bi.EndInit(); bi.Freeze(); } } return bi; }
public static Bitmap ByteArray2Bitmap(byte[] bytes) { Bitmap img = null; try { if (bytes != null && bytes.Length != 0) { MemoryStream ms = new MemoryStream(bytes); img = new Bitmap(ms); } } catch (Exception ex) { Console.WriteLine(ex); } return img; }
public static byte[] Bitmap2Bytes(Bitmap bitmap) { MemoryStream stream = new MemoryStream(); bitmap.Save(stream, ImageFormat.Jpeg); byte[] data = new byte[stream.Length]; stream.Seek(0, SeekOrigin.Begin); stream.Read ( data, 0, Convert.ToInt32(stream.Length) ); stream.Dispose(); return data; }
public static BitmapImage Bitmap2BitmapImage(Bitmap bitmap) { BitmapImage bitmapImage = new BitmapImage(); using (MemoryStream memory = new MemoryStream()) { bitmap.Save(memory, ImageFormat.Png); memory.Position = 0; bitmapImage.BeginInit(); bitmapImage.StreamSource = memory; bitmapImage.CacheOption = BitmapCacheOption.OnLoad; bitmapImage.EndInit(); } return bitmapImage; }
public static BitmapImage ByteArray2BitmapImage(byte[] bytes) { using (var byteArray2Bitmap = ByteArray2Bitmap(bytes)) { BitmapImage bitmapImage = Bitmap2BitmapImage(byteArray2Bitmap); return bitmapImage; } } } }
|
调用
1
| UserHeadImage.Source = ZImageUtils.GetImage(pic);
|
释放
1
| UserHeadImage.Source = null;
|
注意
如果 StreamSource 和 UriSource 均设置,则忽略 StreamSource 值。
要在创建 BitmapImage 后关闭流,请将 CacheOption 属性设置为 BitmapCacheOption.OnLoad。
默认 OnDemand 缓存选项保留对流的访问,直至需要位图并且垃圾回收器执行清理为止。
下面的这种方式会导致内存泄漏
如果在针对图片很大的情况下,或者频繁的调用体积很大的图片,直接引用地址,很可能就会造成内存溢出的问题。
1 2 3
| Uri uri = new Uri(ImageSavePath, UriKind.Absolute); BitmapImage bimg = new BitmapImage(uri); myimage.Source = bitmap;
|
使用Image控件显示图片后,虽然自己释放了图片资源,Image.Source = null 了一下,但是图片实际没有释放。