2

I want to resize the image in my website, but when I using Bitmap to load a image of 14032*19864(png extension), an OutOfMemoryException is thrown. My compiler configuration is any cpu. I was doubting whether the running environment is x64. the code is below:

public ActionResult BimDWGViewer()
{
    Viewer.Uri uri = null;
    string url = Request.Params["u"];
    uri = new Viewer.Uri("image@"+url);
    int width = Int32.Parse(Request.Params["w"]);
    int height = Int32.Parse(Request.Params["h"]);
    Nebula.Nexus.Helpers.ModelUriTranslator.TranslateUri(uri);
    if (uri.IsFileProtocol)
    {
        string path = uri.Path;
        System.Drawing.Bitmap image_source = new System.Drawing.Bitmap(path);
        System.Drawing.Bitmap image_result = new System.Drawing.Bitmap(width,height);
        using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(image_result))
        {
            g.DrawImage(image_source, new System.Drawing.Rectangle(0, 0, width, height), new System.Drawing.Rectangle(0, 0, image_source.Width, image_source.Height), System.Drawing.GraphicsUnit.Pixel);
        }
        MemoryStream output = new MemoryStream();
        image_result.Save(output, System.Drawing.Imaging.ImageFormat.Png);
        byte[] res = output.ToArray();
        output.Dispose();
        image_source.Dispose();
        image_result.Dispose();
        return new FileContentResult(res, "image/png");
    }

}

The exception occurs in the line of

System.Drawing.Bitmap image_source = new System.Drawing.Bitmap(path);
Guy Coder
  • 24,501
  • 8
  • 71
  • 136
majing
  • 25
  • 5
  • Have you tried to open the Task Manager and see how much memory your program uses? – Camilo Terevinto Jan 03 '16 at 14:43
  • It is possible, Graphics wasnt created to handle such images. Use `ImageMagick` http://www.imagemagick.org/script/index.php – Toumash Jan 03 '16 at 14:48
  • Is the path valid? Invalid paths will throw this error in my experience – Jack Jan 03 '16 at 14:52
  • Do what _PhotoShop_ does and use _image tiling_ –  Jan 03 '16 at 14:53
  • the memory is enough. – majing Jan 03 '16 at 14:54
  • I'm sure the path is valid. – majing Jan 03 '16 at 14:55
  • Make sure you don't have “Prefer 32-bit” checked. See [What is the purpose of the “Prefer 32-bit” setting in Visual Studio 2012 and how does it actually work?](http://stackoverflow.com/questions/12066638/what-is-the-purpose-of-the-prefer-32-bit-setting-in-visual-studio-2012-and-how). – dbc Jan 03 '16 at 15:09
  • Are you sure you're running out of memory loading the *source image*? How big is that image? Can you load it in a simple standalone console app? – dbc Jan 03 '16 at 15:11
  • Related: [What is the maximum resolution of C# .NET Bitmap?](https://stackoverflow.com/questions/29175585/what-is-the-maximum-resolution-of-c-sharp-net-bitmap). Your bitmap is 52% of the listed size, so maybe you're running into an undocumented limit. You could try the solution suggested there, which is to use the [System.Windows.Media.Imaging](https://msdn.microsoft.com/en-us/library/system.windows.media.imaging%28v=vs.110%29.aspx) namespace. – dbc Jan 03 '16 at 15:16
  • By the way, I'd use a `using` statement rather than manually calling `Dispose()`, in case an exception is thrown partway through the method. – dbc Jan 03 '16 at 15:20
  • @dbc - Thanks a lot . I'm sure the program running out of memory loading the source image. The source image is about 8MB(14032*19864).I'm not sure I get the point in [What is the maximum resolution of C# .NET Bitmap?](https://stackoverflow.com/questions/29175585/what-is-the-maximum-resolution-of-c-sharp-net-bitmap). – majing Jan 03 '16 at 16:29
  • @dbc - Did you mean that I have to give up using GDI to process such an image? – majing Jan 03 '16 at 16:32
  • @user5550829 - 1) if the source and target are the same size, why are resizing the source? 2) *Did you mean that I have to give up using GDI to process such an image?* ... maybe? You're within a factor of 50% of the stated max resolution of a GDI image. – dbc Jan 03 '16 at 17:07

2 Answers2

2

Make sure you have the gcAllowVeryLargeObjects element set to true in your config file.

There's a 2 GB max for individual allocations in .NET (even when running as a 64-bit process) and it's very possible that one of the classes you're using is doing something internally that bumps into this limit. It's a pretty common problem, and fixing your config file should get you around it.

Update: Per the comments below, the problem that @majing ran into was that Visual Studio was launching his web app in a 32-bit edition of IIS Express. Configuring VS to launch IIS as a 64-bit process fixed the issue.

Mark Waterman
  • 961
  • 7
  • 16
  • Thanks a lot. Now I figure out that It throw such an exception when I allocate 400MB memory. And I set the gcAllowVeryLargeObjects element to true in web.config, but it dosen't work.My complier configuration is "any cpu" and I disabled the "Prefer 32 bit".What should I do next? – majing Jan 04 '16 at 01:55
  • 1
    So you're running this out of a web app then? If you're launching out of Visual Studio right now then the default version of IIS Express that VS launches is 32-bit. You can make VS launch a 64-bit server in Tools->Options->ProjectsAndSolutions->WebProjects and toggle the "Use the 64 bit version of IIS Express..." checkbox. – Mark Waterman Jan 04 '16 at 05:33
  • ...and if you still aren't sure what architecture you're using then just open up Windows Task Manager and look at your app's iisexpress.exe (or w3wp.exe) process. On Win7 and earlier your process will have a `*32` suffix in the detail tab if you're running as a 32-bit process.... and on newer operating systems like Windows 8/8.1/10, the first "Processes" tab should tell you the architecture in parentheses after each process. If you're actually running 64-bit after fixing VS and your config then there's probably a bug in the libraries you're using. – Mark Waterman Jan 04 '16 at 05:51
  • It seems that the IIS Express is 32-bit. But I don't find such a checkbox in vs2012? Does vs2012 not support 64-bit iis express? – majing Jan 04 '16 at 06:58
  • Thank you very much. I upgrade the vs2012 to vs2013 and it works. – majing Jan 04 '16 at 12:41
0

Have you disabled "Prefer 32 bit"?

See http://www.neovolve.com/2015/07/31/disable-prefer-32-bit/

jamespconnor
  • 1,382
  • 14
  • 29