前言
图片我们可能是这样加载的
代码语言:javascript复制<Image Source="{Binding Pic}" Stretch="Fill">
<Image.Clip>
<EllipseGeometry
Center="25,25"
RadiusX="25"
RadiusY="25" />
</Image.Clip>
</Image>
这种方式适合加载程序自身的图片。
但是不建议加载新生成的图片,比如截屏。
因为这样加载一方面图片的内存释放会有问题,容易导致内存泄漏,另一方面,被加载的图片就会处于占用状态,如果此时我们要处理图片比如压缩上传,就会因占用而报错。
正由另一进程使用,因此该进程无法访问此文件。
WPF列表中加载
添加一个转换器
代码语言:javascript复制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;
}
}
}
原来加载的地方改为
代码语言:javascript复制<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中使用转换器来把图片加载到内存中的方式,当然我们也可以在代码中加载。
工具类
代码语言:javascript复制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;
}
/// <summary>
/// Bitmap转byte[]
/// </summary>
/// <param name="bitmap"></param>
/// <returns></returns>
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;
}
}
}
}
调用
代码语言:javascript复制UserHeadImage.Source = ZImageUtils.GetImage(pic);
释放
代码语言:javascript复制UserHeadImage.Source = null;
注意
如果 StreamSource 和 UriSource 均设置,则忽略 StreamSource 值。 要在创建 BitmapImage 后关闭流,请将 CacheOption 属性设置为 BitmapCacheOption.OnLoad。 默认 OnDemand 缓存选项保留对流的访问,直至需要位图并且垃圾回收器执行清理为止。
下面的这种方式会导致内存泄漏
如果在针对图片很大的情况下,或者频繁的调用体积很大的图片,直接引用地址,很可能就会造成内存溢出的问题。
代码语言:javascript复制Uri uri = new Uri(ImageSavePath, UriKind.Absolute);
BitmapImage bimg = new BitmapImage(uri);
myimage.Source = bitmap;
使用Image控件显示图片后,虽然自己释放了图片资源,Image.Source = null
了一下,但是图片实际没有释放。