BenPa

Hi Guys,

I try to load a huge Bitmap (up to 4 MB). Loading the bytes of the image in an array work fine. But if I try to create the Bitmap of the bytes an OutOfMemoryException is thrown.

Is there a way to increase heap size of the application I can see that not all physical RAM is used (~20 MB free), but I canĄ¯t use this ...

Greetings BenPa



Re: .NET Compact Framework Bitmap b = new Bitmap(MemoryStream) ends in OutOfMemoryException

BenPa

I found out something more interesting. The OutOfMemoryException is thrown if the used memory reaches 32 MB. But not only for my application, it is the hole memory used (also from the os and other programs). But iĄ¯ve 50 MB RAM installed, so why I canĄ¯t use the hole memory

Greetings BenPa





Re: .NET Compact Framework Bitmap b = new Bitmap(MemoryStream) ends in OutOfMemoryException

Mario van Zeist

When there is an amount of memory free for your application to use, it doesn't nescesarry mean it's all continues memory. You might have 16MB of free memory divided in 4 chuncks of 4MB, trying to allocate 8MB will fail.

4MB seems like a big picture to me, when you want a screen covering bitmap on windows CE with a resolution of 640*480 pixels you will only need about 600k of image data to fill the screen.

It also depends on the bitmap type you re trying to load. For example you might be loading a 24 or even 32 bit image into your device, the bitmap class will convert that image to 16 bit (565 format) That converting will also take additional memory while loading and downsampling is in progress. I use bitmaps extensivly in my application, and i am loading all my bitmaps as 16 bit, i make sure that i convert the image from 32 or 24 bit downto 16 bit before i transfer that image to my device, so i won't waste any memory, and cpu cycles for downsampling the image. There is an approach you can take, and that is to use the BitMapData class. you can create a bitmap of sufficient size (width/Height) and use LockBits to retrieve a BitMapData class to the pixeldata. There you could read your imagedata into an array. stripping the BMP header, and copying the bits to the buffer pointed to you by the BitMapData class. There are a couple of issues with this approach though. it needs a thorough knowledge of the BMP format, to be able to strip the header, and it you should make sure the bitmapdata already is in the targetdevices pixelformat (16 bit 565 format) to make copying easy. without the need to manually down or up sample the image.

It also needs more memory this way. for example a image of 640*480 needs

1 the memory needed to hold the bitmap class.

2 Then when you call LockBits to get the Bitmapdata class, another copy of the imagedata is made,

3 you will have to creata a buffer to hold the data youre reading from the device.

I personally took a whole different approach using images, and that is building my own Bitmap class, which supports Alphablending aswell, and has some heavy speed advancements ofer the standard BitMap class do to my need to fiddle with pixels alot. I store my data in a specialized format already sampled to the targets device pixelformat, and thanx to my own BitMap class i only need the memory i allocate for the bitmap pixels to load my image, no additional memory needed.





Re: .NET Compact Framework Bitmap b = new Bitmap(MemoryStream) ends in OutOfMemoryException

BenPa

Thanks for your advice. IĄ¯ve read few articles which said that WinCE 5.0 (WM 5.0 is based on CE) have only 32 MB virtual Ram, and your not able to get over this border. But I wonder that my PDA has 50 MB RAM for running applications and maximum 32 MB is used. So I try to find a way to use the rest of the Memory.

Problem is that the image can be loaded in some cases, but sometimes the OutOfMemoryException is thrown, because the memory consumption is near the 32 MB border. So, if I find a way to use the rest of the memory, all problems are fixed for now.

Anyone an idea how to use the rest of the memory

Greetings BenPa





Re: .NET Compact Framework Bitmap b = new Bitmap(MemoryStream) ends in OutOfMemoryException

Mario van Zeist

Youre mixing things up a bit, yes WinCE5.0 has a 32MB virtual address space limit, but assuming youre 50MB for applications and 32MB max virtual address space have anything to do with eachother is false.(Actually.. they do but it's not a 1 on 1 relation)

So if youre application is using 32MB of ram, by no means the 32MB virtual address space is used up, and you can't allocate more, there are different "pools" of memory an application can get his memory from 1 such a "pool' is for example used for "large" memory allocations (Allocations greater then 2MB) (and my guess is here is where youre problem comes from) , also the .NET core assamblies draw their memory from yet another "pool"

if you want a more indepth description about all this you should check the following pages

http://msdn2.microsoft.com/en-us/library/ms836325.aspx

http://blogs.msdn.com/mikezintel/archive/2004/12/08/278153.aspx

Alright where does this leave us.. well i guess back to the drawing board. Smile

Can you specify why you are needing 32MB of memory (Youre stating that your application was roughly using 32MB atm), i am particullary interested in the fact if youre using lots of big objects (images) in your application, or if youre using native dll's for example.

and could you explain why you need the 4MB image loaded into memory , isn't there a way to split it into smaller chuncks as i said on a 640*480 display to fully cover it 600KB of image data is needed, aditional image data is wasted. (No need to have a 24bit image in memory when only 16 bits are displayed), also note that bitmap memory can be more then what you think, for example downsampling and mere displaying of the bitmap can grow youre memory needs) do you need to display it, or manipulate it in someway





Re: .NET Compact Framework Bitmap b = new Bitmap(MemoryStream) ends in OutOfMemoryException

BenPa

First, thanks for your help!!!

The application donĄ¯t need 32 MB of memory, it uses about half of it. The other half is used by the os (WM 5). The application normally loads small images (indexed Bitmaps) into memory and uses them as button images. This all runs fine and no OutOfMemory Exception is thrown.

The big 4 MB images are panoramic views. Because of that I need the hole image in memory for scrolling and zooming. The panoramic views are saved as indexed bitmaps. I donĄ¯t need to manipulate it in any way, only display, scroll and zoom.

I have read in an article that an application can go over the 32 MB border with the function VirtualAlloc() to allocate memory in the "large" memory part. But I donĄ¯t know how to use it from C# and how to pass the allocated memory to C#. Have you any ideas about that

Greetings BenPa





Re: .NET Compact Framework Bitmap b = new Bitmap(MemoryStream) ends in OutOfMemoryException

Ilya Tumanov

This Ą°4MBĄą image ¨C is it 4 MB compressed If so itĄ¯s probably more like 100MB image in memory because as you create bitmaps they are getting uncompressed. You should use Imaging API to deal with these images by loading only small portions of it in memory in uncompressed form. OpenNetcf.org has managed wrapper for that API.






Re: .NET Compact Framework Bitmap b = new Bitmap(MemoryStream) ends in OutOfMemoryException

BenPa

No, its not compressed. Its indexed bitmap. And its not like 100 MB because sometimes it can load the hole image into memory ...

Greetings BenPa





Re: .NET Compact Framework Bitmap b = new Bitmap(MemoryStream) ends in OutOfMemoryException

Peter Nowak (Germany)

Well, but the main question still remains: Is it necessary

There have been already some smart solutions / ideas for your actual problem. Doesn't any of them can be applied on your problem

If you have such a large image to be loaded, then in the requirements on this sth. is "wrong".

You are working with mobile devices, so I guess you want to have a good performing solution, as the hardware used has to be used wisely. If you would even get to the point to get this problem fixed like you want, the solution would end in application with probably bad user experience. Probably you think about this

Cheers, Peter






Re: .NET Compact Framework Bitmap b = new Bitmap(MemoryStream) ends in OutOfMemoryException

Mario van Zeist

using VirtualAlloc won't help you, Say you use VirtualAlloc to allocate 4MB for your image, and the load your image into that array, you will still have to create your 4MB Bitmap, and then at some point you will have to transfer your array to a bitmap, and then again your bitmap will take up 4MB (assuming it's a 8000*480 pixel image), copying your inmemory array to the bitmap means you need to get to the BitmapData of the bitmap (Which again can add yet another 4MB to your memory needs), and then copy the array you loaded into the bitmapdata array (assuming you get the raw bits).

I personally would use the following sollution, which might sounds like some work, but if the panoramic view is the main feature of your application it's well worth it.

Depending on the need to scroll horizontal, or horizontal and vertical. (You state you even want to zoom the image, so i assume you also want to scroll horizontal and vertical) i would first make sure my image is already in 565 pixelformat, then i would divide the image into rectangles (if you only use horizontal scrolling, you can use stripes) (for example rectangles of 64*64 pixels), (Depending on the image type you could even compress the rectangles using SharpZLib for example, but that depends on the amount of compression you get, if you created the Bitmaps using a JPG image, don't bother) then i would save a special file consisting of a header with some information (imagewidth/height, blocksize, and a list of index into the file for each rectangle), then in my application i would create a single bitmap larger then the image i want to display (if the you want to display the image as 640/480 i would use an image of 640+64+64 pixels by 480+32+64+64 pixels, the +32 bits is to get the image to multiple of my used blocksize)

Then i would ovverride the paint function of a panel to Paint my image into the Graphics object of that panel, The complex part of this is if you want to be really effecient, you should not need to load all the rectangles again if you move your view 1 rectangle to the left for example, you can for determine with chuncks of the image i want to display, and load them in part by part) when scrolling you can cleverly determine which additional rectangles you need to load in, you can actually load them in ahead of time to create a smooth scrolling).

example, assume you have an image that looks like this, every letter is a 64*64 block, and assume our screen is 5 characters wide, we start out viewing the left 5 characters, our inmemory image is 7 blocks big

abcdefghijklmnopqrstuvwxyz

i would load 6 blocks into my inmemory buffer, and draw the image to the screen from the first block (a) to the 5th(e)

abcdefx

now after i scroll 64 pixels to the right, my in memory image looks like below, and i draw the image from the second block (b) to the 6th(f)

abcdefg

Now scroll another 64 pixels draw the image from (c) to (g)

hbcdefg

Scroll yet another 64 pixels now it becomes interesting i have to draw in 2 passes first the left part (d)-(g) then the last block(h)

hicdefg

etc, etc,etc, this way while youre scrolling you only need to loadahead 1 stripe of rectangles to keep it smooth.

Well, this might not be the most easiest sollution to make, but it would atleast be very memory conservative, i hope you understand what i mean because i might not have explained it to well, Smile