设备无关位图字节数组到图像:参数无效

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设备无关位图字节数组到图像:参数无效相关的知识,希望对你有一定的参考价值。

我正在使用提供COM接口的电子软件OMICRON MPD和MI。我通过COM接口提供的方法截取屏幕截图,并尝试将byte []保存到图像文件中。

我的代码:

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(@"pathimg.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);

我收到错误:

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

我检查了字节数组的长度:

rawImg.Length
//897832

我可以使用以下内容将上述内存流保存到文件中:

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

我不确定它的意思,但我该如何调试呢?错误在哪里?是我收到的数据是错误的还是C#代码将其保存为图像。

根据COM接口文档,rawImg是与设备无关的位图(格式与.BMP文件相同)。

尝试失败#1

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

对于无效参数,给出与上述相同的错误

结局Solutyon

我观看了一个名为“Hex To BMP:从头开始创建位图”的视频,它帮助我根据我得到的数据构建图像。

我收到的数据包含以字节为单位的图像数据,40字节的DIB标题,以及一些最初的27字节数据(我真的无法弄清楚它是什么)。为了将其转换为图像,它在开头需要一个14字节的文件头,我手动构造如下:

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

请注意,十六进制文件大小(0x0c,0xef,0x82,0x00等于847760字节文件大小)是硬编码的(字节很容易变为动态)。 0x36是实际图像数据开始的位置,其在索引54处为十六进制36。

然后我只是通过偏移到DIB标题开始的位置从我的原始数组中追加数据,在我的情况下是索引27。

下面是我的原始数据的屏幕截图,其中包含最初27个字节的未知数据,以及从索引27开始的DIB标头。

enter image description here

enter image description here

以上是我最终图像十六进制数据的屏幕截图。蓝色是14字节的文件头,红色是DIB头40字节,其余以绿色开头是图像数据。使用“.bmp”扩展名保存此数据并获得图像。

我的代码:

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 = @"pathmyImg.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());
答案

看看Notepad ++转储,看起来这只是32位/像素或4字节ARGB图像的原始字节。您应该能够使用Bitmap(Int32, Int32, Int32, PixelFormat, IntPtr)构造函数并传入原始字节。唯一的问题是找出图像的widthheightstridePixelFormat,但你应该能够通过一些实验来弄清楚这一点。

这是一个示例,我创建了一个与您显示的类似的字节数组:

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:	empitmap.png"); // Could save to another format like .jpg
    }
}
另一答案

尝试代替您的代码片段,如下所示:

byte[] rawImg = ...

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

尝试#2

我的第二个猜测,这可能是一个DIB文件格式,如果是真的,你应该可以在大多数照片查看器/编辑器(如GIMP或其他人)中打开“screen.dib”

byte[] rawImg = array;

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

以上是关于设备无关位图字节数组到图像:参数无效的主要内容,如果未能解决你的问题,请参考以下文章

C++如何把位图保存到数组中

C# 位图图像、字节数组和流!

如何将字节数组中的图像文件数据转换为位图?

将位图转换为字节数组

在 Android 上旋转 YUV 字节数组

当字节数组的源是 jpg 时,从存储的字节数组创建位图并保存到磁盘会引发 GDI+ 异常