繁体   English   中英

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

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

我正在使用提供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(@"path\img.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(@"path\img.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(@"path\img.bmp", System.Drawing.Imaging.ImageFormat.Bmp);

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

最终解决方案

我观看了一个名为“十六进制到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个字节的未知数据,并且DIB标头从索引27开始。

在此处输入图片说明

在此处输入图片说明

上面是我最终图像十六进制数据的屏幕截图。 蓝色是14字节的文件头,红色是40字节的DIB头,其余部分是绿色的图像数据。 使用“ .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 = @"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());

查看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:\temp\bitmap.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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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