c# - BitmapImage OutOfMemoryException 仅在 Windows 8.1 中

标签 c# out-of-memory windows-8.1 bitmapimage

我最近安装了 Windows 8.1 来尝试,但我的宠物项目在它上面崩溃了(相同的二进制文件在一台 Win7 和两台 Win8 机器上运行良好)。

在 BitmapImage.EndInit 中抛出 OutOfMemoryException:

    public static BitmapImage GetResourceImage(string resourcePath, int decodePixelWidth = 0, int decodePixelHeight = 0)
    {
        var image = new BitmapImage();

        var moduleName = Assembly.GetExecutingAssembly().GetName().Name;
        var resourceLocation = string.Format("pack://application:,,,/{0};component/Resources/{1}", moduleName, resourcePath);

        image.BeginInit();
        image.UriSource = new Uri(resourceLocation);
        image.DecodePixelWidth = decodePixelWidth;
        image.DecodePixelHeight = decodePixelHeight;
        image.EndInit();
        image.Freeze();

        return image;
    }
  • 崩溃时进程的任务管理器读数:27MB 内存、302 个句柄、12 个线程、36 个用户对象、34 个 GDI 对象、5.3 GB 可用内存
  • 平台目标是 x86(需要使用 native DLL)
  • 针对不同(随机)图像多次调用方法(资源中有约 250 个 bmp 文件)
  • decodePixelWidth/Height 是随机的,但在有效范围内
  • 异常发生在不同的资源路径和大小
  • 只有当 DecodePixelWidth 或 DecodePixelHeight 不为 0 时才会发生异常
  • 如果我注释掉 DecodePixelWidth 和 DecodePixelHeight setter 并让它加载到原始大小,则不会发生异常

据我通过谷歌搜索了解到,它与 GDI 内部结构有关,但我找不到修复或解决方法。有什么想法(除了使用其他机制来解码和/或调整图像大小——我只需要原始像素数据)?

完整的项目源代码可以在这里找到(链接是相关文件):https://code.google.com/p/lander-net/source/browse/trunk/csharp/LanderNet/Util/BitmapUtils.cs

更新: 我尝试使用 TransformedBitmap 来调整大小,它失败并出现相同的异常。

最佳答案

我已经创建了一个单独的项目并隔离了问题。 看起来像是 GDI 中一个非常奇怪的错误,带有 256 色位图(我所有的图像都是 256 色位图,取 self 用 QBasic 编写的学生时代游戏)。

  • png 和 24 位位图没有问题
  • 加载 24 位位图后,调整 256 色位图大小的问题似乎消失了

所以我的问题通过将所有内容都转换为 PNG 得到解决。

错误已发布到 Microsoft Connect:https://connect.microsoft.com/VisualStudio/feedback/details/812641/bitmapsource-fails-with-outofmemoryexception-on-8-bit-bitmaps

下面是代码。

internal class Program
{
    public static BitmapSource GetResourceImage(string resourcePath, int decodePixelWidth = 0,
        int decodePixelHeight = 0)
    {
        var image = new BitmapImage();

        var moduleName = Assembly.GetExecutingAssembly().GetName().Name;
        var resourceLocation = string.Format("pack://application:,,,/{0};component/Resources/{1}", moduleName, resourcePath);

        image.BeginInit();
        image.UriSource = new Uri(resourceLocation);
        image.DecodePixelWidth = decodePixelWidth;
        image.DecodePixelHeight = decodePixelHeight;
        image.EndInit();
        image.Freeze();
        return image;
    }


    private static void Main()
    {
        new Application();  // register pack uri scheme

        //GetResourceImage("Z40100.png");
        //GetResourceImage("Z40100.bmp");
        //GetResourceImage("Z40100_256color.bmp");
        //GetResourceImage("Z40100_24bit.bmp");

        // Uncomment the following line to fix the crash (or any of the two lines above)

        //GetResourceImage("Z40100_24bit.bmp", 50, 50);
        //GetResourceImage("Z40100_256color.bmp", 50, 50);
        GetResourceImage("Z40100.bmp", 50, 50);
        // GetResourceImage("Z40100.png", 50, 50);
    }
}

关于c# - BitmapImage OutOfMemoryException 仅在 Windows 8.1 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20872510/

相关文章:

c# - 在 RDLC 报告中处理数组和聚合

c# - 如何处理 .NET 下未记录的 API/框架?

C# 泛型 : What does IComparable<Nullable<T>> mean?

c# - 如何通过接口(interface)继承在C#中重新定义一个属性?

java.lang.OutOfMemory错误: Java heap space while reading Excel file into java bean using XLSReader

c++ - 未处理的异常错误

windows-8.1 - 使用表标签的嵌套重复器

android - Glide和recyclerview,内存太大

windows-8 - 在 Visual Studio 2015 中构建 Windows 8 商店应用程序

sqlite - 带有 SQLite 3.8.7.4 的新 Windows 通用应用程序不起作用