[英]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)
构造函数,并且只需传入原始字节即可。 唯一的问题是弄清楚图像的width
, height
, stride
和PixelFormat
,但是您只需做一点点试验就可以弄清楚。
这是一个示例,其中我制作了一个与您显示的字节数组类似的字节数组:
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.