Main Site Documentation

Out of Memory Exception


#1

Not sure whether this question is more of a Gadgeteer/Spider question, or a Glide question, but I’m going to try it here first…feel free to point me to the Glide forum if that’s more apropos.

Anyway, here’s the question…I’m working on a project where I want to capture a picture from the Gadgeteer camera module, display it on the LCD (along with some other graphics, potentially), and then take the contents of the window and convert it to a bitmap, and from there to a base64 string.

I’m using Glide to build the UI, and everything’s working fine right up to the point of the base64 conversion, which throws an OutOfMemoryException.

Here’s the code for initializing and loading the window:


// Resize any loaded Window to the LCD's size.
Glide.FitToScreen = true;

GlideTouch.Initialize();
            
// Load the Window XML string.
window = GlideLoader.LoadWindow(Resources.GetString(Resources.StringResources.Screen1));
            
// Assign the Window to MainWindow; rendering it to the LCD.
Glide.MainWindow = window;

After capturing a picture from the camera to the screen, I then call the following code to grab a bitmap of the screen:


Bitmap outputImage = window.Graphics.GetBitmap();
String imageAttach = ConvertBase64.ToBase64String(outputImage.GetBitmap());

The first line executes without issues, and if I step through, outputImage appears to contain a Bitmap object. But when I call ToBase64String on the outputImage’s GetBitmap result, the aforementioned OutOfMemoryException gets thrown.

Am I doing something wrong here? Is there another way to approach converting an image or window to base64?


#2

The issue you’re having is you actually have 3 copies of the bitmap and are running out of room.

First you have the Bitmap. Then you have the bytes for the Bitmap. Then you have the Base64 encoded Bitmap. It’s just a matter of space.

Try converting the Bitmap to a byte array, then dispose the Bitmap, then Debug.GC(true) then Base64. That [italic]might[/italic] give you enough room to get away with it.

Otherwise you could also try adjusting the size of the custom heap.


#3

Thanks for the quick response…I’ll give that a shot.

This is what happens when you’re used to working with memory in the gigabytes. :slight_smile:


#4

Tried adjusting the custom heap to 4MB, per the instructions here:

http://wiki.tinyclr.com/index.php?title=Custom_Heap

Still getting the OutOfMemoryException, but I’m wondering whether the custom heap is actually coming into play here, since the size of the Bitmap appears to be around 307k, which if I understand correctly, would not automatically be stored in the custom heap.

Any pointers in terms of where to look for the available heap space while debugging?


#5

Updated the code as follows:


Byte[] imageBytes = window.Graphics.GetBitmap().GetBitmap();
window.Graphics.Dispose();
            
String imageAttach = ConvertBase64.ToBase64String(imageBytes);

Grabbing the byte array from the bitmap works fine, as does the call to Dispose, but when I attempt to convert the byte array to base64, it again throws the OutOfMemoryException.

Feel like I’m missing something here…perhaps I’m making this harder than it should be.


#6

Not sure how large are your images but take a look at this http://wiki.tinyclr.com/index.php?title=Custom_Heap


#7

@ Gus,

See my previous reply, which specifically references the wiki page on Custom Heap. :wink:

I believe the images in question are 307k, though I’m a relative newb when it comes to image manipulation and memory management, having been spoiled by my platform for so long not having to worry about it.

If I query window…Graphics.GetBitmap().GetBitmap().Length, the return value is 307200, which I am interpreting to mean that the image is effectively 307kb. Is that correct?

Sorry if I’m asking what seem like dumb questions, but I want to make sure I’m not missing something.


#8

I didn’t notice sorry!

Debug.GC(true); returns the free memory size so you can get to see how much memory is left to analyze your code.


#9

@ dev that seems correct, I am however wondering what other resources you may already be using and just how large that image becomes when Base64 encoded. Perhaps try it on the PC or in the Emulator (that should give you enough memory) then you can check the size.


#10

So, this is interesting. I hadn’t noticed before, but the OutOfMemoryException is occurring in System.Http.dll, when I call:

String imageAttach = ConvertBase64.ToBase64String(imageBytes);

That’s quite puzzling, since the code doesn’t do anything at all network-related (unless there’s something under the covers that’s hitting System.Http.dll.

BTW, if I call Debug.GC(true) after converting the window bitmap to a byte array, it shows what should be plenty of memory available:

Debug.GC(true)
GC: 30msec 2063580 bytes used, 7831884 bytes available

And the additional memory used after allocating the byte array vs. before is consistent with a bitmap size of around 307kb.


#11

By the way, you can use the GHI links to shrink down the the custom heap to give you another 2MB of RAM.


#12

I’m not surprised it’s System.HTTP actually, that would be a logical place to put the Base64 conversion logic since it is mostly used in networking stuff.


#13

@ skewworks

OK, that makes more sense, then. So it looks like my problem may be that the ToBase64String method can’t convert the byte array all at once. So next thing for me to try is chunking it up, and converting it piecemeal.

Thanks for the response!