none
C#2008 PictureBox装载图像的速度问题 RRS feed

  • 问题

  • 使用PictureBox的load方法装载图像的时候,如果图像过大的话,速度会比较的慢。有什么好的方法可以使用图像快速的显示在界面上呢?尤其是打开诸如几十兆或者上百兆,甚至上吉的图像呢?谢谢!
    2010年11月6日 16:35

答案

  • 如果真正要提高性能的话,就不能用 PictureBox 了,自己用 GDI 画。我已经给出了一个基本的方法,您可以参考的。

    具体而言:

    1、利用异步文件加载,将图片文件读入内存。10 MB 的文件大概要花 1 到 2 秒的时间;可以利用 System.File.IO.FileStream 来异步加载。
    2、加载完成后,将得到的文件字节数组 (byte[]) 填充到一个 System.Drawing.Bitmap。
    3、利用并行计算库 (Task Parallel Library) 或者多线程 (ThreadPool, Threads) 的异步方式,将这个 byte[] 均分成段,然后一块一块的画到 Graphics 上去。

    普通的 PictureBox 无法实现并行分块加载,所以,除非自己画,否则,用 .NET 的现有控件,应该是无法再进行大幅的性能提升。

    我提到了 C# 5.0,也许在这个版本中,可能会对此有一些增强。另外,您可以对比一下 WPF 的效率,如果您不熟悉 GDI+,只会用标准控件的话,对比一下 Windows Forms 和 WPF 的效率,选择一个较好的使用。


    Mark Zhou
    • 已标记为答案 pucx 2010年11月17日 10:53
    2010年11月16日 6:44

全部回复

  • 如果图片过大的话,你可以采用异步方式加载图像

    参照

    http://www.cnblogs.com/huangcong/archive/2010/03/26/1697091.html


    http://blog.csdn.net/zx13525079024
    2010年11月7日 4:59
  • 采用异步方式打开也不快啊,也比较的慢啊?请解释下,谢谢。
    2010年11月7日 7:03
  • 图片大的话,加载速度肯定是慢的,你可以在加载过程中显示一个进度条或者显示为等待状态,加载完后再显示图片。
    http://blog.csdn.net/zx13525079024
    2010年11月7日 8:28
  • dear
    若PictureBox.LoadAsync 方法无法满足你的需求,小弟提供一个思路给您参考,
    1.取得图形挡案大小,比如有10MByte
    2.依照挡案大小,建立读挡执行绪(Thread),比如10MByte的挡案,开10条执行绪,每一条负责处理1MByte,并将挡案读取到不同变数
    3.将变数合并
    3.用PictureBox把变数显示出来

    若您要提升效能,可能会花掉相当多的时间来处理,您得自几评估。




    秘訣無它,唯勤而已
    • 已标记为答案 BoberSongModerator 2010年11月12日 5:15
    • 取消答案标记 pucx 2010年11月15日 16:02
    2010年11月8日 1:32
  • 10 MB 的图片加载速度应该在 5 秒以内。如果再大些可能就会更慢。这与 PictureBox 的设计无关。Windows 图片查看器也会很慢的。

    对于这个问题,可以考虑一下两种方法:

    1、由于图片加载慢,可以放一个用户界面级别的提示,如一个进度条,或一个 Loading 光标,利用 LoadAsync 方法异步加载,这样不会阻塞用户界面线程,这样至少 UI 不会无响应。注意,异步加载并不能提高加载速度,而是利用其它方式 (可能是线程,或者 Windows 消息) 加载而已。

    2、利用楼上 MVP 的方法,将数据作为字节分段读出,然后合并成图片。这个比较麻烦一些,也不好用。因为拿到图片后,还要把它关联到一个 HDC 上面然后用 Graphics 画在 PictureBox 上。

    另外,C# 5.0 的异步编程模型库中,会提供 PictureBox.LoadTaskAsync() 方法,会对目前的图像加载速度慢的问题作一定优化,但具体的实现,可能会根据开发计划而改变。


    Mark Zhou
    • 已标记为答案 BoberSongModerator 2010年11月12日 5:14
    • 取消答案标记 pucx 2010年11月15日 16:02
    2010年11月8日 13:02
  • 10 MB 的图片加载速度应该在 5 秒以内。如果再大些可能就会更慢。这与 PictureBox 的设计无关。Windows 图片查看器也会很慢的。

    对于这个问题,可以考虑一下两种方法:

    1、由于图片加载慢,可以放一个用户界面级别的提示,如一个进度条,或一个 Loading 光标,利用 LoadAsync 方法异步加载,这样不会阻塞用户界面线程,这样至少 UI 不会无响应。注意,异步加载并不能提高加载速度,而是利用其它方式 (可能是线程,或者 Windows 消息) 加载而已。

    2、利用楼上 MVP 的方法,将数据作为字节分段读出,然后合并成图片。这个比较麻烦一些,也不好用。因为拿到图片后,还要把它关联到一个 HDC 上面然后用 Graphics 画在 PictureBox 上。

    另外,C# 5.0 的异步编程模型库中,会提供 PictureBox.LoadTaskAsync() 方法,会对目前的图像加载速度慢的问题作一定优化,但具体的实现,可能会根据开发计划而改变。


    Mark Zhou

    mark

    C# 5.0已經上市了???


    秘訣無它,唯勤而已
    2010年11月8日 14:08
  • 正在开发中,不过我已经写了一些有关 C# 5.0 的博客文章,有兴趣可以参考 http://www.markzhou.com


    Mark Zhou
    2010年11月15日 13:46
  • 非常抱歉,前几天因有事而离开,所以没有跟进。但是从上面大家的讨论可以看出,还是没有实质性的提出解决方案来,但是对于图片的加载,像很多大公司的软件,比如徕卡公司的ERADS软件等其打开大图片的加载速度就很快。请问该如何改进呢?谢谢!

    2010年11月15日 16:06
  • 非常抱歉,前几天因有事而离开,所以没有跟进。但是从上面大家的讨论可以看出,还是没有实质性的提出解决方案来,但是对于图片的加载,像很多大公司的软件,比如徕卡公司的ERADS软件等其打开大图片的加载速度就很快。请问该如何改进呢?谢谢!

    dear
    要针对效能优化是要复出代价的,绝非三言两语就能解决,请问你有使用多执行绪(Thread),尝试去处理吗?

    秘訣無它,唯勤而已
    2010年11月15日 17:19
  • 这个还未曾尝试使用,主要是不清楚这个东西怎么使用于图像的加载当中来。谢谢。

    2010年11月16日 5:32
  • 如果真正要提高性能的话,就不能用 PictureBox 了,自己用 GDI 画。我已经给出了一个基本的方法,您可以参考的。

    具体而言:

    1、利用异步文件加载,将图片文件读入内存。10 MB 的文件大概要花 1 到 2 秒的时间;可以利用 System.File.IO.FileStream 来异步加载。
    2、加载完成后,将得到的文件字节数组 (byte[]) 填充到一个 System.Drawing.Bitmap。
    3、利用并行计算库 (Task Parallel Library) 或者多线程 (ThreadPool, Threads) 的异步方式,将这个 byte[] 均分成段,然后一块一块的画到 Graphics 上去。

    普通的 PictureBox 无法实现并行分块加载,所以,除非自己画,否则,用 .NET 的现有控件,应该是无法再进行大幅的性能提升。

    我提到了 C# 5.0,也许在这个版本中,可能会对此有一些增强。另外,您可以对比一下 WPF 的效率,如果您不熟悉 GDI+,只会用标准控件的话,对比一下 Windows Forms 和 WPF 的效率,选择一个较好的使用。


    Mark Zhou
    • 已标记为答案 pucx 2010年11月17日 10:53
    2010年11月16日 6:44