前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >WPF中加载本地图片推荐方式

WPF中加载本地图片推荐方式

作者头像
码客说
发布2023-11-05 09:37:49
发布2023-11-05 09:37:49
69900
代码可运行
举报
文章被收录于专栏:码客码客
运行总次数:0
代码可运行

前言

图片我们可能是这样加载的

代码语言:javascript
代码运行次数:0
运行
复制
<Image Source="{Binding Pic}" Stretch="Fill">
    <Image.Clip>
        <EllipseGeometry
            Center="25,25"
            RadiusX="25"
            RadiusY="25" />
    </Image.Clip>
</Image>

这种方式适合加载程序自身的图片。

但是不建议加载新生成的图片,比如截屏。

因为这样加载一方面图片的内存释放会有问题,容易导致内存泄漏,另一方面,被加载的图片就会处于占用状态,如果此时我们要处理图片比如压缩上传,就会因占用而报错。

正由另一进程使用,因此该进程无法访问此文件。

WPF列表中加载

添加一个转换器

代码语言:javascript
代码运行次数:0
运行
复制
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
代码运行次数:0
运行
复制
<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
代码运行次数:0
运行
复制
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
代码运行次数:0
运行
复制
UserHeadImage.Source = ZImageUtils.GetImage(pic);

释放

代码语言:javascript
代码运行次数:0
运行
复制
UserHeadImage.Source = null;

注意

如果 StreamSource 和 UriSource 均设置,则忽略 StreamSource 值。 要在创建 BitmapImage 后关闭流,请将 CacheOption 属性设置为 BitmapCacheOption.OnLoad。 默认 OnDemand 缓存选项保留对流的访问,直至需要位图并且垃圾回收器执行清理为止。

下面的这种方式会导致内存泄漏

如果在针对图片很大的情况下,或者频繁的调用体积很大的图片,直接引用地址,很可能就会造成内存溢出的问题。

代码语言:javascript
代码运行次数:0
运行
复制
Uri uri = new Uri(ImageSavePath, UriKind.Absolute);
BitmapImage bimg = new BitmapImage(uri);
myimage.Source = bitmap;

使用Image控件显示图片后,虽然自己释放了图片资源,Image.Source = null 了一下,但是图片实际没有释放。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-11-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • WPF列表中加载
  • 代码中加载
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档