Efficient byte[] to BitmapImage and vice versa conversion in C# - c#

I need to get the BitmapImage from the byte array. Currently I'm working with MemoryStream
(byte[] -> MemoryStream -> BitmapImage) but it seems to be not efficient.
The same situation in the other way round - I need to get the byte array representing the BitmapFrame. Again, I'm doing that with MemoryStream.
What is the most efficient way to accomplish that task? Is it possible to speedup the conversion?
Thank you in advance for the replies and hints!
Cheers

Im using BitmapSource.CopyPixels to extract the bytes from the BitmapSource and then BitmapSource.Create to create a new image from the byte array.
I'm not sure how effective it is though, but it is sufficient for my purposes (I can extract the pixels, recolor them and then paste them back on a 2000*2000 image with barely noticeable delay).

Related

Encode a Bitmap as a Jpeg

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?

Importing an Image from an XML File

I'm trying to produce a system which takes an image in OpenCV, writes it to XML, reads it from XML, and displays it in an Image control in a WPF application.
The problem I'm having is that I'm unclear as to how .NET classes (e.g. BitmapImage) process images from a byte array. I've tried a number of methods and gotten various errors - too numerous to post unless required.
I was wondering if someone could point me in the right direction regarding this? What I want to know is how does the data need to be presented to a .NET object in order to display it in an Image control?
Thanks in advance for your help - it is much appreciated.
EDIT: I expect what I need to do is convert the XML into a byte array and use that, along with a definition of the format, to instantiate a BitmapImage object or equivalent to use as source for the Image control. What I'm not sure of is how to do this.
Use int cvSaveImage(const char* filename, const CvArr* image)
to save the file as an Image.The image format is chosen based on the filename extension
No need to store it in XML if you can directly store it as Image file.
The .NET classes requires an Image.That's it.
Note:
If you want to store red,green,blue values as comma separated strings, it would be very inefficient.Save it in Base64 instead.You can then convert it into bytes and feed it to any .NET image class.Also the .NET ImageConverter Class may be very helpful.
I found that the issue was (presumably) that I wasn't Base64 encoding the XML data before writing it. Thus the solution is to Base64 encode the data before writing to XML, Base64 decoding it on the other side, reading the data as a byte array and using that to instantiate a MemoryStream and then a BitmapImage object.
Thanks for your help everyone.
You can use:
public static BitmapSource Create(
int pixelWidth,
int pixelHeight,
double dpiX,
double dpiY,
PixelFormat pixelFormat,
BitmapPalette palette,
Array pixels,
int stride
)

Processing on large bitmaps (up to 3GB)

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

Reading one bit from a pbm (portable bitmap image)

I want to read a pbm (portable bitmap format) image having depth one bit per pixel and store that data in a file, so I can perform some operation on bits.
I think in C# the smallest data that can be read is 1 byte so how can I read a bit?
You can't read a bit directly. But you can read a byte and then get the bits from that byte. Or, better yet, read a bunch of bytes into an array and then create a BitArray.
Or ... is this "portable bitmap format" supported directly by the Bitmap class? Bitmap does support a 1 bit per pixel format. It might be as simple as calling the Bitmap constructor to load from a file or a stream.
More information on your problem will get you a better answer.

Problem with BitmapFrame rendering (created from byte array) in C#

Here is the situation:
I have got the array of bytes containing the bitmap header together with the bitmap data. I know the offset of data, and I need to generate BitmapFrame for later rendering.
I wanted to avoid array cells copying and created a wrapper for a part of the array
(
ArraySegment ).
Then I render this bitmap together with a primitive into the RenderTargetBitmap, which is, in turn, saved to the same array (in place of data) using CopyPixels.
I have noticed, that if I work on the original data, with an array wrapper I get the wrong final image. However if I copy the same data to another array and provide it to static Create method of BitmapFrame class, the result is correct.
Do you have any ideas what happens?
Thank you in advance for the replies!
Cheers
OK, I have identified the problem - a property of ArraySegment returns the original array - no the subarray...

Categories

Resources