Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BitmapImage OutOfMemoryException only in Windows 8.1

I've installed Windows 8.1 recently to try, and my pet project is crashing on it (same binary works fine on one Win7 and two Win8 machines).

OutOfMemoryException is being thrown in BitmapImage.EndInit:

    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;
    }
  • Task manager readings for the process on crash: 27MB memory, 302 handles, 12 threads, 36 user objects, 34 GDI objects, 5.3 GB RAM available
  • Platform target is x86 (required because of native DLL usage)
  • Method is called many times for different (random) images (there are ~250 bmp files in resources)
  • decodePixelWidth/Height are random, but within valid range
  • exception happens on different resource paths and sizes
  • exception happens only when DecodePixelWidth or DecodePixelHeight is not 0
  • exception never happens if I comment out DecodePixelWidth and DecodePixelHeight setters and let it load to original size

As I understand from googling, it has something to do with GDI internals, but I can't find a fix or workaround. Any ideas (besides using some other mechanism to decode and/or resize images - I only need raw pixel data)?

Complete project source code can be found here (link is to the file in question): https://code.google.com/p/lander-net/source/browse/trunk/csharp/LanderNet/Util/BitmapUtils.cs

UPDATE: I've tried to use TransformedBitmap for resizing, it fails with the same exception.

like image 493
Pavel Tupitsyn Avatar asked Oct 21 '22 17:10

Pavel Tupitsyn


1 Answers

I've created a separate project and isolated the issue. Looks like a very strange bug in GDI with 256 color bitmaps (all my images are 256 color bitmaps taken from my school days game written in QBasic).

  • there are no problems with png and 24 bit bitmaps
  • problems with resizing 256 color bitmaps seem to go away after loading a 24 bit bitmap

So my issue is fixed by converting everything to PNG.

Bug is posted to Microsoft Connect: https://connect.microsoft.com/VisualStudio/feedback/details/812641/bitmapsource-fails-with-outofmemoryexception-on-8-bit-bitmaps

Below is the code.

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);
    }
}
like image 109
Pavel Tupitsyn Avatar answered Oct 24 '22 11:10

Pavel Tupitsyn