Share via


Image class in C# is not working on large size images(> 15MB approx)

Question

Thursday, July 9, 2015 7:20 AM

I'm using Image class in C# for further image processing like the code below.

Image image = Image.FromFile(filePath);

So when the file is greater than 15MB(approximately), it throws "Out of Memory" exception. Can anyone say the reason behind this issue?..

Thanks in Advance.

All replies (25)

Thursday, July 9, 2015 1:58 PM âś…Answered | 1 vote

"I can achieve resizing the image using third party C++ made dlls like MagickImage.NET but I can't achieve the same using Image class in C#."

The following code should do the resize without consuming 2GB of memory:

using (var stream = File.OpenRead("D:\\large.jpg"))
using (var image = Image.FromStream(stream, useEmbeddedColorManagement: true, validateImageData: false))
using (var thumb = image.GetThumbnailImage(1024, 1024, null, IntPtr.Zero))
{
    thumb.Save("D:\\small.jpg");
}

"I want the user to select large files for profile picture."

The JPG files in the DropBox example has 80MB, not 15MB as you claimed before. It's unclear how and why a user would upload such a large file. Most websites that value their reliability and security would probably limit the size of the images a user can upload.


Thursday, July 9, 2015 7:42 AM

Both Tools offer a free trail.


Thursday, July 9, 2015 7:53 AM | 1 vote

Is 15MB the size of the image file? Is it a JPEG image? Such an image could easily take 1GB when loaded into memory and if your application happens to be 32 bit an OOM exception is not surprising.


Thursday, July 9, 2015 8:39 AM

Indeed. And when you handle those images on your own, have free'd all unneeded references to old images? Garbage collection runs often to late on such memory wasting objects.


Thursday, July 9, 2015 8:42 AM

Thank you for your response. If JPEG format is the problem, then which format can I use to handle these large images?..


Thursday, July 9, 2015 8:56 AM

Thank you for your perusal.

Yes i freed unneeded references...Is this problem related to a particular image file format?


Thursday, July 9, 2015 8:57 AM | 2 votes

It is not that the JPEG format is the problem. The previous posters are just saying that JPEG is a compressed format, so it is deceptive in terms of how much memory it really needs. A JPEG file that is 15MB on disk is actually a whole lot of data that needs to get uncompressed in memory in order to display or process it.

I know that information may not help you, but as Stefan suggested, ensure you are tidying up all other memory, disposing of disposable objects etc to ensure you have as much memory available as possible.

The specification of the machine you are running your code on may also be a factor, i.e. 32-bit vs 64-bit.

(And where do these images come from? Is it possible to simply generate lower resolution - and hence smaller - images in the first place?)


Thursday, July 9, 2015 9:16 AM

Thank you for your response.

I don't think memory disposal is the problem since I've checked this issue in a sample project which contains just this line below. It reacts the same.

Image image = Image.FromFile(filePath);

And I'm using Image  class, only to generate lower resolution image..


Thursday, July 9, 2015 9:57 AM | 1 vote

There's little we can help you with if you don't provide enough details. What resolution does that image have? Is that a 32 bit application or not?


Thursday, July 9, 2015 10:53 AM

Thank you for your consideration Mike and sorry for not detail oriented.

Please find attached the link for simple demo on this issue: https://www.dropbox.com/s/m0slihcjfhccrtk/ImageSample.zip?dl=0

This is an ASP application. Again thank you for you are helping in this.


Thursday, July 9, 2015 11:30 AM | 1 vote

Please tell us ahead of time that this is ASP. Different memroy considerations apply to it. Like this:

Troubleshooting System.OutOfMemoryExceptions in ASP.NET : Microsoft Support Team's IIS Blog : The Official Microsoft IIS Site

Loading anything sizeable into the memory of a ASP-Server is a bad idea. Make any processing on the client or with a seperate programm.

2nd ASP.Net question should generally be asked over in the proper forum:

http://forums.asp.net/

As was already said, the size on the disk or network means squat. Every single compression has to be undone when working with images.
21,6k Squared pixel image needs a whole friggin LOT of memory. That is at least 466.560.000 Pixel. If each thsoe only needs 4 byte uncompressed, that is 1.866.240.000 byte or almost 2 GiB!

With that image you could actually make an example of what do to wrong when processing images in ASP/general programmin.


Thursday, July 9, 2015 12:09 PM

I'm using Image class in C# for further image processing like the code below.

Image image = Image.FromFile(filePath);

So when the file is greater than 15MB(approximately), it throws "Out of Memory" exception. Can anyone say the reason behind this issue?..

Thanks in Advance.

The size of the file doesn't directly matter.  It's the number of pixels that matters.  What is width and height of the file that you are having trouble with?  Can you examine the file (right click on it and choose properties, and look at the Details of the image) and determine its dimensions?  (Image width and Image height, measured in pixels.)


Thursday, July 9, 2015 12:20 PM

Width: 21600px

Height: 21600px

So can I change the pixel before using Image class (Image image = Image.FromFile(filePath);)

Thanks,

Sam Azpan


Thursday, July 9, 2015 12:21 PM

Thank you Christopher.

Though my application is ASP, i face the same issue with windows application also.


Thursday, July 9, 2015 12:30 PM

Thank you Christopher.

Though my application is ASP, i face the same issue with windows application also.

Yes, because you seem to not read properly. So one more time:

Size on Disk and Network is irrelevant for processing. You might as well tell us your shoe size.

If you want to work with an image, you HAVE TO transform it into a 32-bit color depth bitmap in memory.
A 21600x21600 Pixel bitmap at 32-bit color depth takes just under 2 GiB of RAM. (And more like it is 64-bit color depth).

Final Test:

1. Just try to open that iamge with any image processing programm. Gimp. Paint. Does not matter as long as it is not just a preview programm.
2. If it actually works to open that image, save it as bitmap.
3. Measure the size of said bitmap. THAT IS THE MEMORY THIS IMAGE NEEDS WHEN LOADED INTO A MEMORY. Not a single byte less. That is the amount of memory the line "Image.FromFile(filePath);" tries to allocate. And the value is quite frankly insanely high.

Edit: Gimp finally manage to open it. It measure at around 4,4 GiB in memory. Gimp in total needs 4,2 GiB.

You are trying to allocate beyond 4 GiB of ram, of course that fails!


Thursday, July 9, 2015 1:09 PM

Thank you Christopher.

Its really a big issue. So Christopher what would be the solution for this.


Thursday, July 9, 2015 1:28 PM

What is it you are actually trying to do with these files?

Because using the Image class, which necessarily decompresses the file to process it, may simply not be possible: The reason you are getting an out-of-memory exception is because you are genuinely running out of memory! There is no magic that will make that error disappear except to not try and allocate that much memory in the first place.


Thursday, July 9, 2015 1:40 PM

Thank you.

I want the user to select large files for profile picture.

But in the background i save that large image in server which is now possible and then I want to assign that image as a profile picture but this requires using Image class.

This is my present scenario.

Note: I can achieve resizing the image using third party C++ made dlls like MagickImage.NET but I can't achieve the same using Image class in C#.


Thursday, July 9, 2015 2:26 PM | 1 vote

"I can achieve resizing the image using third party C++ made dlls like MagickImage.NET but I can't achieve the same using Image class in C#."

The following code should do the resize without consuming 2GB of memory:

using (var stream = File.OpenRead("D:\\large.jpg"))
using (var image = Image.FromStream(stream, useEmbeddedColorManagement: true, validateImageData: false))
using (var thumb = image.GetThumbnailImage(1024, 1024, null, IntPtr.Zero))
{
    thumb.Save("D:\\small.jpg");
}

"I want the user to select large files for profile picture."

The JPG files in the DropBox example has 80MB, not 15MB as you claimed before. It's unclear how and why a user would upload such a large file. Most websites that value their reliability and security would probably limit the size of the images a user can upload.

There's one rather serious problem with that code.  It will not save a jpg file.

It will save a PNG file with a .jpg extension.  (Probably an accident waiting to happen!) The documentation for Image.Save mentions this in its remarks section.

To get Image.Save to save a jpeg file, you have to provide an ImageFormat.Jpeg argument, or provide a ImageCodecInfo object to specify the details of the jpeg encoding parameters.


Thursday, July 9, 2015 2:31 PM

"It will save a PNG file with a .jpg extension"

Thanks, I completely forgot about that :)


Thursday, July 9, 2015 11:26 PM

Width: 21600px

Height: 21600px

So can I change the pixel before using Image class (Image image = Image.FromFile(filePath);)

Thanks,

Sam Azpan

The usual solution is to just don't allow users to upload files bigger then a certain size in pixels.
I am pretty sure you can check the dimensions before you even try to work with it. Just the saved, compressed file in memory carries it's width and height same as the saved, compressed file on disk.

Getting that data might be tricky, however. You effectively have to do your own parsing of he file:
http://stackoverflow.com/questions/111345/getting-image-dimensions-without-reading-the-entire-file

Let'S get realistic:
No sane person would try to upload a 21600x21600 Pixel image for something that will only be displayed as 200x200 pixel. I would not even allow the uploaded file to be bigger then 1000x1000 if I am generous. Even that resizing is a lot of processing work and memory bandwidth on your end.

I tried to make your example image my profile picture for this forum. Just the trying to upload a 78.8 MiB JPEG failed. HTTPS Formulars were apparently not designed for such high data amounts through my slow upload.


Friday, July 10, 2015 1:52 AM

With ARGB that kind of resolution translate to about 1.7GB of memory. By default classic ASP application pools recycle at less than 1GB on IIS6. Sam had better go and check the recycle settings too.


Friday, July 10, 2015 6:04 AM

Thank you Mike. It works well with Image class when I set "validateImageData=false". But is there any consequences?.

" It's unclear how and why a user would upload such a large file":

Now my requirement is to allow users to upload large images for profile pictures. But yet, requirements have a nature to evolve over time. :)


Friday, July 10, 2015 6:59 AM | 1 vote

"But is there any consequences?"

validateImageData simply forces the image to be loaded in memory. That was likely done to ensure that you don't get an exception when you try to actually use the image later if the file is corrupted. Since you're immediately using the image validateImageDate=false won't make a difference in this regard.


Friday, July 10, 2015 9:17 AM

With ARGB that kind of resolution translate to about 1.7GB of memory. By default classic ASP application pools recycle at less than 1GB on IIS6. Sam had better go and check the recycle settings too.

Just don't allow such a humongous image to be uploaded in the first place! A nearly 80 MiB JPEG? As basis for a Profile Picture?

If it's a JPEG or PNG and bigger then 100 KiB, it is just to big or detailed to bother storing. 800 times that size is just plain insane.
There are artistic, multicolored images that are not 100 KiB in size as .png or .jpg