简体   繁体   中英

Device Independent Bitmap Byte Array to Image : Parameter is not valid

I am working with a electronic software OMICRON MPD and MI that provides a COM Interface. I am taking a screenshot via the methods provided by COM Interface and attempting to save the byte[] to an image file.

My code:

byte[] rawImg = ...
MemoryStream mstream = new MemoryStream(rawImg);
ImageConverter imageConverter = new System.Drawing.ImageConverter();
System.Drawing.Image image = imageConverter.ConvertFrom(rawImg) as System.Drawing.Image; //error line
image.Save(@"path\img.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);

I get the Error:

System.ArgumentException' occurred in System.Drawing.dll Parameter is not valid

I have checked the length of the byte array:

rawImg.Length
//897832

I can save the above memory stream to a file using the following:

using (FileStream file = new FileStream(@"path\img.txt", FileMode.Create, FileAccess.Write))
{
    mstream.WriteTo(file);
}

I am not sure what it means, but how do I debug this? Where is the error? Is it the data I am receiving that is erroneous or the C# code to save it as an image.

According to the COM Interface documentation, the rawImg is device-independent bitmap (the format is identical to a .BMP file).

Failed Attempt #1

ImageConverter imageConverter = new System.Drawing.ImageConverter();
            Image image = imageConverter.ConvertFrom(rawImg) as Image; //error line
            image.Save(@"path\img.bmp", System.Drawing.Imaging.ImageFormat.Bmp);

gives same error as above about invalid parameter

Final Solution

I watch a video called "Hex To BMP: Creating a Bitmap From Scratch", which helped me in constructing the image from the data I was getting.

I was receiving a data that had image data in bytes, the 40 bytes DIB Header, and some initial 27 bytes of data (I couldn't really make out what it is). For this to be translated into an image it needed a 14 bytes file header at the beginning, which I manually constructed like so:

byte[] fileHeader = { 0x42, 0x4d, 0x0c, 0xef, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00 };

Notice that the file size in hex (0x0c, 0xef, 0x82, 0x00 which equals 847760 bytes file size) is hard coded (byte can easily be made dynamic). 0x36 is where the actual image data begins which is at index 54 that is 36 in hex.

Then I just appended that data from my original array by offsetting to where the DIB Header begin which in my case was index 27.

Below is Screenshot of my raw data with the initial 27 bytes of unknown data and with DIB Header starting at index 27.

在此处输入图片说明

在此处输入图片说明

Above is a screenshot of my final image hex data. The blue is the file header of 14 bytes, red is DIB header 40 bytes, and rest starting with green is image data. Save this data with ".bmp" extension and you got a image.

My Code:

byte[] imgData, newImgData;
byte[] fileHeader = { 0x42, 0x4d, 0x0c, 0xef, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00 };
newImgData = new byte[847760];
BinaryFormatter bf = new BinaryFormatter();
string path2 = @"path\myImg.bmp";
using (MemoryStream ms = new MemoryStream())
{
  bf.Serialize(ms, value);
  mgData = ms.ToArray();

 }
 for(int i = 0; i < fileHeader.Count(); i++)
 {
       newImgData[i] = fileHeader[i];
 }

  int indx = 14;

  for (int i = 27; i < imgData.Count(); i++)
  {
       newImgData[indx] = imgData[i];
       indx++;
  }

  System.IO.File.WriteAllBytes(path2, newImgData.ToArray());

Looking at the Notepad++ dump it appears this is just the raw bytes of 32 bit-per-pixel or 4 byte ARGB image. You should be able to use the Bitmap(Int32, Int32, Int32, PixelFormat, IntPtr) constructor and just pass in the raw bytes. The only issue will be figuring out the width , height , stride , and PixelFormat of the image but you should be able to figure that out with a little bit of experimentation.

Here's an example where I made a byte array similar to the one you've shown:

byte[] bytes = new byte[] {
    0,64,128,128,
    0,64,128,128,
    0,64,128,128,
    0,64,128,128,
    0,64,128,128,
    0,64,128,128,
    0,64,128,128,
    0,64,128,128,
};

unsafe
{
    fixed (byte* pBytes = bytes)
    {
        int width = 4; // Your width
        int height = 2; // Your height
        int stride = width * 4; // Your stride
        Bitmap bitmap = new Bitmap(width, height, stride, PixelFormat.Format32bppArgb, new IntPtr(pBytes));
        bitmap.Save(@"c:\temp\bitmap.png"); // Could save to another format like .jpg
    }
}

Try just istead of your code snippet something like this:

byte[] rawImg = ...

MemoryStream mstream = new MemoryStream(rawImg);
File.WriteAllBytes("screen.bmp", mstream.ToArray());

Attempt #2

My second guess, this could be a DIB file format, if it is true, you should be able to open "screen.dib" in most photo viewers/editors (like GIMP or others)

byte[] rawImg = array;

File.WriteAllBytes("screen.dib", rawImg);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM