I'm working on some university project and got stuck with memory issue.
I load a bitmap which takes about 1,5GB on HDD with code below:
Bitmap bmp = new Bitmap(pathToFile);
The issue is that the newly created Bitmap object uses about 3,5GB of RAM which is something I can't understand (that's really BIG wrapper :E). I need to get to the pixel array, and the use of Bitmap class is really helpful (I use LockBits() method later, and process the array byte per byte) but in this case it's total blocker. So here is my question:
Is there any easy way to extract the pixel array without lending additional 2gb?
I'm using c# just to extract the needed array, which is later processed in c++ - maybe I can extract all needed data in c++ (but conversion issue appears here - I'm concentrating on 24bgr format)?
PS: I need to keep the whole bitmap in memory so splitting it into parts is no solution.
PS2: Just to clarify some issues: I know the difference between file extension and file format. The loaded file is uncompressed bitmap 3 bytes per pixel of size ~1.42GB (16k x 32k pixels), so why Bitmap object is more than two times bigger? Any decompressing issues and converting into other format aren't taking place.
Consider using Memory Mapped Files to access your HUGE data :).
An example focused on what you need can be found here: http://visualstudiomagazine.com/articles/2010/06/23/memory-mapped-files.aspx
It's in managed code but you might as well use it from equivalent native code.
Let me know if you need more details.
You can use this solution , Work with bitmaps faster in C#
http://www.codeproject.com/Tips/240428/Work-with-bitmap-faster-with-Csharp
Or you can use memory mapped files
http://visualstudiomagazine.com/articles/2010/06/23/memory-mapped-files.aspx
You can stop memory caching.
Instead of
Bitmap bmp = new Bitmap(pathToFile);
Use
var bmp = (Bitmap)Image.FromStream(sourceFileStream, false, false);
see https://stackoverflow.com/a/47424918/887092
Related
I'm trying to make a screen sharing program, the program flows will be like this:
capture screen
slice to 9
compare new slice with old slice
replace the different slice
upload to web (with new slice)
But I've got some problems with replacing the slices (in replace function). From all the source I have searched I need to convert the bitmap image (the slice) to string, then I can replace. but there's no example for converting bitmap double array to strings.
Is there any possibility to replace the image without convert it to strings?
Why would you need to replace bitmap data using a string as intermediate? You can use bitmap manipulation functions just fine. Also, I'm having trouble understanding your algorithm. You get a bitmap of the whole screen. Then you cut it into 9 parts (are those the corners, edges and center?), compare each of the slices to their old versions one by one, replace the ones that changed, and then you upload the whole bitmap? Don't you want to upload each of the slices separately, only uploading the ones that changed? Otherwise it doesn't really make sense to do the slicing at all, or does it?
Now, it's true that converting the data to string lets you use the string comparison functions and other stuff like that, but that's an awful idea. The fastest way to compare two byte arrays would be using the memcmp function in msvcrt.dll. This answer gives you the solution to that - https://stackoverflow.com/a/2038515/3032289, including reading the data from the original bitmaps.
Then you just send the slices that aren't the same as their older versions and you're done, no replacing needed.
Probably the best way is to perform a Base64 encoding
Google for base64 C++ source code.
First, this question is NOT about "how to save a Bitmap as a jpeg on your disk?"
I can't find (or think of) a way of converting a Bitmap with Jpeg compression, but keep it as a Bitmap object. MSDN clearly shows how to save a Bitmap as a JPEG, but what I'm looking for is how to apply the encoding/compression to the Bitmap object, so I can still pass it around, in my code, without referencing the file.
One of the reasons behind that would be a helper class that handles bitmap, but shouldn't be aware of the persistency method used.
All images are bitmaps when loaded into program memory. Specific compressions are typically utilized when writing to disk, and decompressing when reading from disk.
If you're worried about the in-memory footprint of an image you could zip-compress the bytes and pass the byte array around internally. Zipping would be good for lossless compression of an image. Don't forget that many image compressions have different levels of losiness (sp?) In other words, the compression throws away data to store the image in the smallest number of bytes possible.
De/compression is also a performance tradeoff in that you're trading memory footprint for processing time. And in any case, unless you get really fancy, the image does need to be a bitmap if you need to manipulate it in any way.
Here is an answer for a somewhat similar question which you might find interesting.
Bitmap does not support encoded in-memory storage. It is always unencoded (see the PixelFormat enum). Problably you need to write your own wrapper class/abstraction, or give up on that idea.
var stream = new MemoryStream()
Bitmap.Save(Stream, ImageFormat)
Does it what you need?
I do have a Bitmap Array that contains more than 500 Bitmaps object. I need to convert each single Bitmap object within the Array into a binary Array. I'm using the MemoryStream class to achieve this:
using (MemoryStream ms = new MemoryStream())
{
images[0].Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
byte[] byteData = ms.ToArray();
}
I would like to know if there is other way to achieve this. I'm not sure how expensive is this process.
Thanks
I've done some speed tests and converting to ImageFormat.Bmp is the fastest. It doesn't need to do any compression. Though the best format will also depend on what you plan to do with the data after that.
It's also worth considering where the Bitmaps came from in the first place. If you're loading them in from a file it may be worth it to switch things around and read the file data in first, then create your Bitmap objects from it after that.
By choosing Gif you are making a CPU/memory trade off which you most likely don't want. Specifically the Gif is going to be smaller but is going to take some time to compress (unless the images are already in the format) relative to using a BMP.
If you are copying these around enough that you have memory bandwidth issues (and can't fix that) this is a good idea, but otherwise you should stick with BMP. Really though, for 500 images I would expect this to take 1-2 seconds at the most so you probably don't need to worry about this sort of micro optimization. If its taking to long you can move to unmanaged code which will likely perform better because you will have finer control over memory allocations and copies.
How can i compress and image file(*bmp,*jpeg) in C#,
I have to display some images as background on my controls, i m using following code to scale my image
Bitmap orgBitmap = new Bitmap(_filePath);
Bitmap regBitmap = new Bitmap(reqSize.Width, reqSize.Height);
using (Graphics gr = Graphics.FromImage(reqBitmap))
{
gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
gr.DrawImage(bmp, new RectangleF(0, 0, reqSize.Width, reqSize.Height));
}
It giving me the required bitmap.
My problem is if orginal bitmap is to heavy(2 MB) then when i load 50 image it feed all my memory, i want to compress the image as much i can without losing the so much quality,How can i do the same in .NET ?
Do you definitely need the large images to be present at execution time? Could you resize them (or save them at a slightly lower quality) using an image editing program (Photoshop, Paintshop Pro etc) beforehand? There seems to be little point in doing the work every time you run - especially as editing tools are likely to do a better job anyway.
Of course, this won't work if it's something like the user picking arbitrary images from their hard disk.
Another point: are you disposing of the bitmaps when you're finished with them? You aren't showing that in your code... if you're not disposing of the original (large) bitmaps then you'll be at the mercy of finalizers to release the unmanaged resources. The finalizers will also delay garbage collection of those objects.
JPEG always lose something, PNG don't.
This is how you encode and decode PNG with C#:
http://msdn.microsoft.com/en-us/library/aa970062.aspx
Perhaps I'm misunderstanding things, but why not convert the bitmaps to jpg's before you import them into your project as control backgrounds?
Good luck compressing JPEG. :) It's compressed already. As for your BMPs, make them JPEGs.
I'm loading a Bitmap from a jpg file. If the image is not 24bit RGB, I'd like to convert it. The conversion should be fairly fast. The images I'm loading are up to huge (9000*9000 pixel with a compressed size of 40-50MB). How can this be done?
Btw: I don't want to use any external libraries if possible. But if you know of an open source utility class performing the most common imaging tasks, I'd be happy to hear about it. Thanks in advance.
The jpeg should start with 0xFF 0xD8. After that you will find various fields in the format:
Field identifier 2 bytes
Field length, excluding field identifier. 2 bytes.
Variable data.
Parse through the fields. The identifier you will be looking for is 0xFF 0xC0. This is called SOF0, and contains height, width, bit depth, etc. 0xFF 0xC0 will be followed by two bytes for the field length. Immediately following that will be a single byte showing the bit depth, which will usually be 8. Then there will be two bytes for height, two for width, and a single byte for the number of components; this will usually be 1 (for greyscale) or 3. (for color)
This isn't something I've tried myself, but I think you might need to acccess the picture's EXIF information as a start.
Check out Scott Hanselman's blog-entry on accessing EXIF information from pictures.
Standard .NET System.Drawing namespace should have all that you need,
but it probably won't be very efficient. It'll load the whole thing into RAM, uncompress it, convert it (probably by making a copy) and then re-compress and save it. If you aim for high performance, I'm afraid you might need to look into C/C++ libraries and make .NET wrappers for them.
As far as I know jpg is always 24 bpp. The only thing that could change would be that it's CMY(K?) rather then RGB. That information would be stored in the header. Unfortunately I don't have any means of creating a CMYK image to test whether loading into a Bitmap will convert it automatically.
The following line will read the file into memory:
Bitmap image = Image.FromFile(fileName);
image.PixelFormat will tell you the image format. However, I can't test what the file load does with files other than 24bpp RGB jpgs. I can only recommend that you try it out.