0

I'm still learning Emgu CV and I need to load Image from byte array which contains a PNG32 data. I'm loading image as follows (this is working example):

FileStream fs;
Bitmap bitmap;
Image<Rgba, byte> image;

bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
image = new Image<Rgba, byte>(width, height)
{
    Bytes = data // data is my byte array
};

if(File.Exists("1.png"))
    File.Delete("1.png");

image.Save("1.png");
fs = new FileStream("1.png", FileMode.Open);
bitmap = (Bitmap)Image.FromStream(fs); // this is image what I need
fs.Close();
File.Delete("1.png");

because, if I will use just

Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
Image<Rgba, byte> image = new Image<Rgba, byte>(width, height)
{
    Bytes = data // data is my byte array
};
bitmap = image.Bitmap; // this is image what I need

the background of my bitmap will be white, however my initial image has a transparent background.

So, I think that there is more optimal way to load Image from binary data than in my first example, but I don't know it. Can anyone help?

Vlad i Slav
  • 59
  • 2
  • 12
  • That original code is already bad... according to the MSDN specs, [Bitmaps created from stream need that stream to remain open for the lifetime of the image.](https://learn.microsoft.com/en-us/dotnet/api/system.drawing.bitmap.-ctor?view=netframework-4.7.2#System_Drawing_Bitmap__ctor_System_IO_Stream_) Using that image after disposing the stream often leads to crashes. – Nyerguds Feb 15 '19 at 10:18
  • What exactly do you mean with "PNG32 data"? is it just a PNG file? If so, you can just make a `MemoryStream` out of it, and use the `new Bitmap(stream)` constructor on that: – Nyerguds Feb 15 '19 at 10:21
  • On a related note... why are you initialising your `bitmap` variable with a new Bitmap? That object is completely unused. – Nyerguds Feb 15 '19 at 10:55
  • @Nyerguds, as you know (I hope), PNG-file may be of three formats: 8-bit (indexed image), 24-bit (image with no transparent) and 32-bit. "PNG32" means, that binary data has one byte of red, one byte of green, one byte of blue and one byte of alpha for each pixels of my image, i.e. my image is 32-bit. Using MemoryStream leads to errors - it does not read data correctly. – Vlad i Slav Feb 16 '19 at 11:09
  • @Nyerguds, I initialized bitmap variable with a new Bitmap because I need to specify PixelFormat of my image. – Vlad i Slav Feb 16 '19 at 11:11
  • The initialisation of that `bitmap` variable is irrelevant, since; _you don't use that object._ You don't put anything _into_ that initialized object; you just _replace_ the contents of that _variable_ with a _new_ object that comes out of `Image.FromStream(fs)` (or `image.Bitmap`). – Nyerguds Feb 16 '19 at 12:49
  • I still don't understand what you mean with `PNG32 data`, by the way. If it's really just a png file it should work fine without all that mess. You could upload the file somewhere so people could check it out. – Nyerguds Feb 16 '19 at 12:55
  • https://previews.dropbox.com/p/thumb/AAUs6VG1HwUMD4D_G2GmBZsrPOaEQB-Ho2EeXASeUTJSKLHwVzgTCLvxeQVYvt10N_oitEqjnRPsTwYX1NqL15L6-h4HyT_W-2xsIZKOcbkAQbTuaic1aUm5Di9wEkybI-gnUgId_pHCRXkcq9trKApJIqxrDFZ4rshfGHkg3H8TToMfPWQcVyaWrUVlzxE57ZATtDrUX3JN9LhGXDOSgmTbbP5EtUq5fUsHyThA7l9IXQ/p.png?size_mode=5 – Vlad i Slav Feb 16 '19 at 15:18
  • https://previews.dropbox.com/p/thumb/AAWMFvwP0Qk-VNtxW7hQfYPR9ILdnbWjq0U7tmRtQq4VwQLrvClnTSpcpy8tXl6kc9SJt5MLgxOWncU5lZ1fp9p7XikXYOw7QRLLq7VXcluNcTwMsNLLvHj1zRD_XjjjUD_OnkFkmjlqcnY3EqVLdmOcTbUZrhC2g0EVS8x3JdXRpfxGeGpvUZjjC3CRAEm0MAFn7a16wlmUMyMt1eODlVuHbjB2RK3qufNs71Iv7Fwx5g/p.png?size_mode=5 – Vlad i Slav Feb 16 '19 at 15:18
  • @Nyerguds, I mean a **color depth** of image. As you see, there are 2 images above: 24-bit format and 32-bit format. Besides, there is a 8-bit (indexed) images. If you don't know **this**, you cann't give me the help. – Vlad i Slav Feb 16 '19 at 15:24
  • I know about the concept of image depth, but I don't understand why you call it "data" and not just "a png file". Neither of these links work, by the way; get the actual dropbox share urls, not the thumbnails it generates – Nyerguds Feb 16 '19 at 16:14
  • @Nyerguds, I call it data because I don't work with images directly. I work with **byte arrays** of images. And I know, that byte arrays of 8-bit, 24-bit and 32-bit images is different. That's why I call my images "data" and that's why I call my data "PNG32". If you know about color depth, I don't need to upload images, because you must understand, what I mean. – Vlad i Slav Feb 16 '19 at 17:16

1 Answers1

2

If your byte array is all the data from the PNG file, then the image dimensions and colour depth are all simply part of that file's header data, and you don't need to do anything special at all. Why are you even using that Image<Rgba, byte>? You seem to want it as Bitmap in the end... so just load it as Bitmap directly:

Bitmap bitmap;
using (MemoryStream ms = new MemoryStream(data))
using (Bitmap tmp = new Bitmap(ms))
    bitmap = new Bitmap(tmp);

That should be the only code you need. The new Bitmap(tmp) at the end will make a new object that is not tied to the stream that the tmp one is attached to, making the object usable without the previously mentioned issues concerning disposed streams. Additionally, when making a new Bitmap from an existing Bitmap, the result will always be 32bpp ARGB.

If you want to preserve the original colour depth, you can replace the new Bitmap(tmp); by the CloneImage function I described here.

If your files include 8-bit PNG files that contain transparency, the System.Drawing classes will convert them to 32 bit ARGB for some reason. To get around that, look at this answer I gave to a question on that subject.

Nyerguds
  • 5,360
  • 1
  • 31
  • 63
  • Thank you. But my task is save original color depth of png file. – Vlad i Slav Feb 17 '19 at 08:53
  • 1
    You never said that. You only ever said you wanted to preserve _transparency_, I edited the question and linked you to some other answers I gave here that deal with preserving the original image format. That should solve your issues. – Nyerguds Feb 17 '19 at 09:45
  • @VladiSlav If the answer helped you to resolve your issue, please [accept it as answer](https://stackoverflow.com/help/someone-answers). – Nyerguds Feb 18 '19 at 11:42